Linux: How to know where a process was started and how it was started?
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!
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
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:
-
cwd
link to the current working directory -
fd
a dir with links to the open files (file descriptors) -
cmdline
read it to see what command line was used to start the process -
environ
the environment variables for that process -
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.
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} ]
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
Try ps axww | grep perl
to get the full command line of your process. It looks like top
just trimmed a long line.