66

I was checking a Linux box and found a perl process running and taking a good share of cpu usage. With top, i could only perl in process name.

When i pressed c, to view the command-line, it showed /var/spool/mail. Which does not make sense, since this is directory.

My questions are:

1) Why did this happen? How this perl process could mask its command-line? 2) What is the most reliable way of finding out where and how a process was started?

Thanks!

9 Answers 9

48

In most cases just running ps is usually sufficient, along with your favorite flags to enable wide output. I lean towards ps -feww, but the other suggestions here will work. Note that if a program was started out of someone's $PATH, you're only going to see the executable name, not the full path. For example, try this:

$ lftp &
$ ps -feww | grep ftp
lars      9600  9504  0 11:30 pts/10   00:00:00 lftp
lars      9620  9504  0 11:31 pts/10   00:00:00 grep ftp

It's important to note that the information visible in ps can be completely overwritten by the running program. For example, this code:

int main (int argc, char **argv) {
        memset(argv[0], ' ', strlen(argv[0]));
        strcpy(argv[0], "foobar");
        sleep(30);
        return(0);
}

If I compile this into a file called "myprogram" and run it:

$ gcc -o myprogram myprogram.c
$ ./myprogram &
[1] 10201

And then run ps, I'll see a different process name:

$ ps -f -p 10201
UID        PID  PPID  C STIME TTY          TIME CMD
lars     10201  9734  0 11:37 pts/10   00:00:00 foobar

You can also look directly at /proc/<pid>/exe, which may be a symlink to the appropriate executable. In the above example, this gives you much more useful information than ps:

$ls -l /proc/9600/exe
lrwxrwxrwx. 1 lars lars 0 Feb  8 11:31 /proc/9600/exe -> /usr/bin/lftp
1
  • 3
    all, in all, the files in /proc will provide all information about a program, exe will be a link to executable, cwd to current working directory, fd directory contains links to open files (including standard input, output and standard error) Feb 8, 2011 at 16:47
85

Most reliable way is to look at the /proc dir for the process. Each process has a /proc/<pid>/ directory where it keeps information like:

  1. cwd link to the current working directory
  2. fd a dir with links to the open files (file descriptors)
  3. cmdline read it to see what command line was used to start the process
  4. environ the environment variables for that process
  5. root a link to what the process considers it's root dir (it will be / unless chrooted)

There's more cool info on each process /proc, but with those above you will be able to exactly know what is going on.

Also, using ps auxf will show you who forked what so you may get a better idea who is calling your perl.

4
  • 3
    I always use Process Explorer on Windows and wondered if there was an equivalent on Linux. That switch does it all! ps auxf ... nice! Apr 30, 2013 at 19:31
  • 6
    +1 for the f parameter for ps, that did it for me! Jun 4, 2014 at 10:08
  • 4
    +1 for teaching me what seems like such a fundamental concept... /proc contains process information! who knew?? all i ever looked in there for was version and cpuinfo and stuff... plus this solves my actual problem because my router's version of ps ignores all parameters
    – Nacht
    Oct 16, 2014 at 5:18
  • 1
    @coredump : and if the process calledchroot()before, how I can know which directory/proc/ᴘɪᴅ/cwdcorresponds to ? Mar 1, 2017 at 20:18
29

for me, just now, i found that pstree gave a much clearer indication of how a process was started, than ps aux

it looks like this:

  ├─lightdm─┬─Xorg
  │         ├─lightdm─┬─init─┬─apache2───2*[apache2───26*[{apache2}]]
  │         │         │      ├─at-spi-bus-laun─┬─dbus-daemon
  │         │         │      │                 └─3*[{at-spi-bus-laun}]
  │         │         │      ├─at-spi2-registr───{at-spi2-registr}
  │         │         │      ├─dbus-daemon
  │         │         │      ├─dropbox───29*[{dropbox} ]
1
  • 1
    And in order to find what you're looking for easier, use pstree | grep --color 'pattern\|$'
    – Ufos
    Dec 18, 2022 at 0:49
14

you can use:

systemctl status <PID>

or with the name of the process:

systemctl status $(pgrep perl)

This will deliver information on systemd services that started your process.

I found this hint here

1
  • 1
    ... unless, of course, the process was not started by systemd. After all, there are a lot of legacy services that may still sidestep systemd... Jul 10, 2022 at 13:13
3

Try ps axww | grep perl to get the full command line of your process. It looks like top just trimmed a long line.

2

Wihtout consulting the man page for the exact flags, an easy way to fund out what the command line and the start time is, ps auxwww should work. You can make it more elegant if desired by reading the man page.

2

Try use command fuser -vu /var/spool/mail This command will displays you the PIDs of processes using the specified files or file systems. In the default display mode, each file name is followed by a letter denoting the type of access:

c - current directory. e - executable being run. f - open file. f is omitted in default display mode. r - root directory. m - mmap'ed file or shared library.

Maybe it will help you to move forward your searching to answer you are looking for. I don't know if it helps you but maybe you will find out some useful information.

1

Two commands spring to mind:

1) get the start time for the process out of 'ps'.

$ ps -ax -o pid,start,comm
  PID  STARTED COMMAND         USER
    1   Feb 06 init            root
    2   Feb 06 kthreadd        root
[...]
  13147 19:09:48 chrome          hcooper
  13270 19:13:51 chrome          hcooper
  13386 19:18:34 bash            hcooper

2) lastcomm, which now I check, I don't have installed. Anyhow the man page description says:

   lastcomm prints out information about previously executed commands. If
   no arguments are specified, lastcomm will print info about all of the
   commands in acct (the record file).

But as a few people have said, "ls -al /proc/" will tell you a lot!

0

If you know the PID (process id), use pstree with -s (show parent processes) and -p (show PIDs):

$ pstree -sp 23419
systemd(1)───systemd(2339)───tmux: server(31195)───bash(23234)───sudo(23396)───apt-get(23398)───http(23419)

Then use ps to get the details of parent processes:

$ ps 23398 23396
  PID TTY      STAT   TIME COMMAND
23396 pts/4    S+     0:00 sudo apt-get update
23398 pts/4    S+     0:00 apt-get update

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .