What does sh -c "ps -l" mean in linux? - linux

My Command Interpreter is bash shell.After opening terminal on my OS(cent OS), I have executed following commands:
scenario 1
$sh -c "ps -l"
UID PID PPID TIME CMD
3038 2577 2504 00:00:00 bash
3038 2992 2577 00:00:00 ps
scenario 2
$sh
$ps -l
UID PID PPID TIME CMD
3038 2577 2504 00:00:00 bash
3038 3005 2577 00:00:00 sh
3038 3006 3005 00:00:00 ps
Observe PID and PPID of ps.
In scenario 1, I am executing ps -l command on sh shell. So it's parent should be sh i.e., it's PPID should be PID of sh. But ps -l command listing that it's parent is bash. I am not understanding what is happening exactly. I am understanding the difference between scenario 1 and scenario 2. But when I am executing the same commands on another OS(ubuntu), I am getting same listing under ps -l in scenario 3 and scenario 4, as below:
scenario 3
$sh
$ps -l
UID PID PPID TIME CMD
3038 2577 2504 00:00:00 bash
3038 2991 2577 00:00:00 sh
3038 2992 2991 00:00:00 ps
scenario 4
$sh
$ps -l
UID PID PPID TIME CMD
3038 2577 2504 00:00:00 bash
3038 3005 2577 00:00:00 sh
3038 3006 3005 00:00:00 ps
Here in both scenarios, I am getting PPID of ps CMD as PID of sh. What is happening exactly. Is my interpretation wrong?

When you type a command, bash just fork then execve the command. scenario 3 and scenario 4 are the case.
While sh -c 'ps -l' depends on shells.
On my linux distribution, the result of ls -l `which sh` islrwxrwxrwx 1 root root 4 Oct 6 14:06 /usr/bin/sh -> bash.
When -c is present, bash execve the following command directly. While another shell like fish does not.
fish -c 'ps -l'
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
0 S 1000 711 710 0 80 0 - 5707 wait pts/5 00:00:00 bash
0 S 1000 1519 711 0 80 0 - 7054 wait pts/5 00:00:00 fish
0 R 1000 1526 1519 0 80 0 - 9266 - pts/5 00:00:00 ps
What execve does is replacing the current process image with a new process image.fork creates a new process.

Related

How to use grep and cut together to extract a certain text from an output using bash [duplicate]

This question already has answers here:
How to get process ID of background process?
(9 answers)
Closed 1 year ago.
Below is the output of executing two commands ads2 svcd& and ps -aux|grep ads2
nvidia#nvidia-desktop:~$ ads2 svcd&
[1] 4593
nvidia#nvidia-desktop:~$ ps -aux|grep ads2
nvidia 4593 0.5 0.0 39796 23864 pts/0 Sl 08:20 0:00 /opt/ads2/arm-
linux64/bin/ads2svcd
nvidia 4603 0.0 0.0 6092 672 pts/0 S+ 08:20 0:00 grep --color=auto ads2
nvidia#nvidia-desktop:~$
nvidia#nvidia-desktop:~$
the command ads2 svcd& runs a process related to ads2 software. with ps -aux|grep ads2 i displayed the whole processes that contains the name "ads2".
Now What i'm trying to do is to get the process number of the ads2 which in this example is 4593. So i wrote the follwing bash script:
#!/usr/bin/env bash
process="$(ps -aux|grep ads | grep 'nvidia' | cut -d' ' -f 3)"
echo "The current ads2 process is " $process
The bash script outputs the following:
nvidia#nvidia-desktop:~$ ./test.sh
The current ads2 process is
As you see the process number is not filtered. So what i'm i doing wrong?
thanks in advance
List all the processes in the current shell with $$ built-in variable
ps --forest -gp $$
PID TTY STAT TIME COMMAND
3809 pts/1 Ss 0:01 bash
4896 pts/1 T 0:00 \_ vim file.json
22965 pts/1 S+ 0:00 \_ ssh dw
3607 pts/0 Ss 0:01 bash
2500 pts/0 R+ 0:00 \_ ps --forest -gp 3607
3327 tty2 Ssl+ 0:00 /usr/lib/gdm3/gdm-x-session --run-script i3
3329 tty2 Sl+ 8:12 \_ /usr/lib/xorg/Xorg vt2 -displayfd 3 -auth /run/user/1000/gdm/Xauthority -background none -noreset -keeptty -verbose 3
3346 tty2 S+ 0:03 \_ i3
Just see the pid of them:
ps -opid --forest -gp $$
PID
3809
4896
22965
3607
2688
3327
3329
3346
If you need to use grep for any reason, use -opid,cmd with current shell:
ps -opid,cmd -gp $$ | grep vim
3851 grep --color=auto vim
4896 vim file.json
For all, just use -e
ps -e -opid,cmd | grep vim
4141 grep --color=auto vim
4896 vim file.json
The complete one, we have to ignore the grep itself:
ps -e -opid,cmd | grep vim | grep -v grep | cut -d' ' -f 2
4896
Without double grep using comm option for ps
ps -opid,comm -gp $$ | grep vim
4896 vim
of course the simplest one is pgrep
pgrep vim
4896
NOTE for variable assignment there should NOT be any space:
# wrong
ads2ProcessId = $(pgrep ads2)
# right
ads2ProcessId=$(pgrep ads2)

Could SIGKILL fail?

I've encountered this piece of behavior where even after issuing SIGKILL using kill -9 the process is not terminating. the command in question here is cat
# ps -ef | grep 19275
root 19275 1 0 08:50 ? 00:00:00 [cat]
root 22964 21578 0 09:05 pts/1 00:00:00 grep --color=auto 19275
# kill -9 19275
# echo $?
0
# ps -ef | grep 19275
root 19275 1 0 08:50 ? 00:00:00 [cat]
#
some background
I've executed this command for ((i=0; i<28; i++)); do cat </dev/zero >${i} & done as part of my test, for some strange reason when I tried to terminate this using
pkill -TERM cat did not work
pkill -9 cat did not work
kill -9 pid did not work
if memory is restriction here I do believe there is enough memory available here
# free -g
total used free shared buff/cache available
Mem: 23 18 2 0 2 3
Swap: 59 2 56
any hints ? apart from reboot
I tried your logic it worked for me with kill -9 and even with
killall cat, but it take some time to kill all 28 instances

pgrep command not returning PID

I am trying to find the PID of a process (motion_sensor.py), but pgrep returns nothing. Why does it not return the process id?
pgrep -u www-data motion_sensor.py
ps -ef | grep "motion_sensor" returns
root 7149 1 93 Apr25 ? 15:59:08 python motion_sensor.py
www-data 31872 23531 0 14:09 ? 00:00:00 sh -c sudo python /home/pi/Desktop/PiControl/motion_sensor.py
root 31873 31872 0 14:09 ? 00:00:00 sudo python /home/pi/Desktop/PiControl/motion_sensor.py
root 31874 31873 47 14:09 ? 00:14:30 python /home/pi/Desktop/PiControl/motion_sensor.py
pi 32645 32202 0 14:39 pts/0 00:00:00 grep --color=auto motion_sensor.py
Normally pgrep applies the search pattern to process names. The process name in this case is python and not motion_sensor.py. If you want to grep for the full path rather than just the process name you need to pass -f:
pgrep -u www-data -f motion_sensor.py
Check man pgrep
the requirement is to find out PID of a process,
So you can try :
ps aux | grep www-data motion_sensor.py

Get the pid of the shell script and save it into a lockfile

I do my backups with rsnapshot which creates a lockfile with the process pid inside. Now I would like to make a backup from the rsnapshots backup, so I´m looking for a way to create this lockfile for the second/external backup.
The shell script should like this:
check if a lockfile exists, if yes wait and try again(i´m doing this with a while true loop)
get the pid of this shell script and save it as a rsnapshot lockfile
start the second/external backup
delete the lockfile
How can I get the PID and save it as a rsnapshot lockfile ?
The PID is stored in $$
Like
echo $$ > thisscriptpidfile
For any application, you can find its Process ID using the Unix shell itself, using ps. Example below is a very reduced list from ps. PS will show you not only the PID, but also the owner, as well as the Parent Process ID (as in which process started this particular process.)
userX# ps -ef | more
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 Oct19 ? 00:00:00 /sbin/init
root 2 0 0 Oct19 ? 00:00:00 [kthreadd]
root 3 2 0 Oct19 ? 00:00:02 [migration/0]
root 4 2 0 Oct19 ? 00:04:48 [ksoftirqd/0]
root 5 2 0 Oct19 ? 00:00:00 [migration/0]
root 6 2 0 Oct19 ? 00:00:00 [watchdog/0]
...
root 27 2 0 Oct19 ? 00:00:00 [pm]
root 28 2 0 Oct19 ? 00:00:00 rsnapshot
root 29 2 0 Oct19 ? 00:00:00 [xenbus]
Now let's start finding which Process is interesting to us. I am not familiar with rsnapshot, so I've put dummy data in the examples.
userX# ps -ef | grep rsnapshot
root 28 2 0 Oct19 ? 00:00:00 rsnapshot
ec2-user 7233 1497 0 11:32 pts/0 00:00:00 grep rsnapshot
Note that it does not give you the "header" information, only matching lines, thanks to grep.
Your second "column" is the PID. Noteworthy: ps shows every process, including the grep you just ran. Your commands/scripts need to be wary of this and strip out these items. I will use awk in the next example to do just that.
And now to expand further, getting the PID into a file. We need to confirm we have a PID, and if so, create the command to create the lock file:
userX# ps -ef | grep rsnapshot | awk '$0!~/grep/ && $2~/[0-9]/{print "echo "$2" > rsnapshot.lck"}'
echo 28 > rsnapshot.lck
If no PID for rsnapshot exists, then there will be no output. As writtent, awk will review each line, and if it does not contain the string "grep" AND there is any digit [0-9] in the second field, then print the command to be run - but not actually run the command.
The final step is to invoke the command, from the awk output.
userX# ps -ef | grep rsnapshot | awk '$0!~/grep/ && $2~/[0-9]/{print "echo "$2" > rsnapshot.lck"}' | sh
Adding "| sh" causes all output to be invoked as a command. If awk does not find rsnapshot, then there is no command to run.

In Linux,pdftoppm command is running two processes for single file

root#test:/var/lib/tomcat/webapps/logs# ps aux | grep ppm
root 25522 0.0 0.0 1844 500 ? SN 14:13 0:00 sh -c /bin/bash -c "pdftoppm -f 1 -l 1 /pdf/input.pdf test/processing/output"
root 25523 49.6 0.7 18192 12620 ? RN 14:13 0:59 pdftoppm -f 1 -l 1 /pdf/input.pdf /test/processing/output
root 25539 0.0 0.0 2016 636 ? R+ 14:15 0:00 grep ppm
I am not familiar with this command. Why two processes are running I can't understand.
These are not two pdftoppm processes. The following is the pdftoppm process:
root 25523 49.6 0.7 18192 12620 ? RN 14:13 0:59 pdftoppm -f 1 -l 1 /pdf/input.pdf /test/processing/output
The following is the process for the shell command:
root 25522 0.0 0.0 1844 500 ? SN 14:13 0:00 sh -c /bin/bash -c "pdftoppm -f 1 -l 1 /pdf/input.pdf test/processing/output"
The first line in your grep output is for the shell command that was executed. The second line was for the actual pdftoppm invocation. The third line was for the grep. (Both your shell command and grep contained the string pdftoppm, which were a part of the process list when queried.)
The shell script is most likely excuted via a system call (that's what it would be in c). This system call invokes a command processor (PID 25522 in your case) to interpret the command.
The command itselves is the process with PID 25523.
In C the exec command family executes a command without invoking a command line interpreter.

Resources