Why does grepping PID keep changing? - pid

I want to write a bashscript to kill a process by ID, but I can't even seem to get the PID working since it keeps changing. Why is this?
Jacks-MBP:~ Knof$ ps aux | grep "firefox"
Knof 515 0.0 4.3 4822060 723232 ?? U 10:28PM 4:57.15 /Applications/Firefox.app/Contents/MacOS/firefox
Knof 4489 0.0 0.0 2436888 812 s002 S+ 12:36AM 0:00.00 grep firefox
Jacks-MBP:~ Knof$ ps aux | grep "firefox"
Knof 515 0.0 4.3 4822060 723232 ?? U 10:28PM 4:57.15 /Applications/Firefox.app/Contents/MacOS/firefox
Knof 4491 0.0 0.0 2436888 812 s002 S+ 12:36AM 0:00.00 grep firefox
Jacks-MBP:~ Knof$ ps aux | grep "firefox"
Knof 515 0.0 4.3 4822060 723232 ?? U 10:28PM 4:57.15 /Applications/Firefox.app/Contents/MacOS/firefox
Knof 4493 0.0 0.0 2436888 812 s002 S+ 12:36AM 0:00.00 grep firefox
Jacks-MBP:~ Knof$ ps aux | grep "firefox"
Knof 515 0.0 4.3 4822060 723232 ?? U 10:28PM 4:57.15 /Applications/Firefox.app/Contents/MacOS/firefox
Knof 4495 0.0 0.0 2435864 800 s002 S+ 12:36AM 0:00.00 grep firefox

Every time you fire
ps aux | grep "firefox"
you are restarting a grep process. It's doesn't indicate the PID of the running Firefox located at
/Applications/Firefox.app/Contents/MacOS/firefox
in your case.
In your case, 515 is the process to kill.

Each time a process is started, it is assigned a new (incrementing) PID; even if the executable and all arguments are the same.
You'll notice the PID of "firefox" is the same for all of your four calls, indicating that is hasn't been restarted meanwhile.
The PID for "grep" changes as it has been started (and terminated) for each call.

Related

Problem running ps to find PID with multiple users

When I run the following code and then run ps to see the processes running, I only get 4 ./a.out running processes even though there are 5 forks. Why is that? How am I able to see the other fork? Also, if multiple people are using my computer, running the same process a.out, how can I terminate only my processes, using only linux commands? Please help.
PID TTY TIME CMD
32941 ttys000 0:00.10 -bash
34098 ttys000 0:00.08 less
33651 ttys000 0:00.00 ./a.out
33652 ttys000 0:00.00 ./a.out
33654 ttys000 0:00.00 ./a.out
33655 ttys000 0:00.00 ./a.out
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#define N 5 /* How many children to make. */
#define D 1200 /* Sleep 1200 seconds = 20 minutes */
int main(void)
{
int i;
pid_t p;
for (i = 0; i < N; i++) {
p = fork();
if (p == 0) {
close(0);
close(1);
close(2);
if (i == 2) {
setsid();
}
sleep(D);
return 0;
}
}
return 0;
}
All five processes are running, but you're using the ps command that only shows processes associated with your session, but the setsid() called for i=2 sets a different session, so the default ps options won't show you.
$ ps
PID TTY TIME CMD
3048 pts/0 00:00:00 bash
8288 pts/0 00:00:00 a.out
8289 pts/0 00:00:00 a.out
8291 pts/0 00:00:00 a.out
8292 pts/0 00:00:00 a.out
8301 pts/0 00:00:00 ps
$ ps -fe | grep a.out
steve 8288 1 0 13:39 pts/0 00:00:00 ./a.out
steve 8289 1 0 13:39 pts/0 00:00:00 ./a.out
steve 8290 1 0 13:39 ? 00:00:00 ./a.out <-- missing one
steve 8291 1 0 13:39 pts/0 00:00:00 ./a.out
steve 8292 1 0 13:39 pts/0 00:00:00 ./a.out
steve 8303 3048 0 13:40 pts/0 00:00:00 grep --color=auto a.out
$
By default, ps only displays processes with the same session id as itself and associated with a terminal. When you changed the session id of one of the processes, you disqualified it from being listed. ps x will include all of your processes.
By default, ps only lists the processes belong to you. You can be sure of this by using ps ux to include the owners of the processes in the output.
You can use the kill utility to kill these processes. Unless you are root, you can't kill other processes owned by others even if you tried.

Output a for loop into a array

I need the below 4th row idle outputs to be put into a array and then take a average out of the same . below is lparstat output of an aix system.
$ lparstat 2 10
System configuration: type=Shared mode=Uncapped smt=4 lcpu=16 mem=8192MB psize=16 ent=0.20
%user %sys %wait %idle physc %entc lbusy app vcsw phint %nsp %utcyc
----- ----- ------ ------ ----- ----- ------ --- ----- ----- ----- ------
2.6 1.8 0.0 95.5 0.02 9.5 0.0 5.05 270 0 101 1.42
2.8 1.6 0.0 95.6 0.02 9.9 1.9 5.38 258 0 101 1.42
0.5 1.4 0.0 98.1 0.01 5.5 2.9 5.17 265 0 101 1.40
2.8 1.3 0.0 95.8 0.02 8.9 0.0 5.37 255 0 101 1.42
2.8 2.0 0.0 95.2 0.02 10.8 1.9 4.49 264 0 101 1.42
4.2 1.7 0.0 94.1 0.02 12.2 0.0 3.66 257 0 101 1.42
0.5 1.5 0.0 98.0 0.01 6.3 1.9 3.35 267 0 101 1.38
3.1 2.0 0.0 94.9 0.02 12.1 2.9 3.07 367 0 101 1.41
2.3 2.2 0.0 95.5 0.02 9.8 0.0 3.40 259 0 101 1.42
25.1 25.5 0.0 49.4 0.18 89.6 2.6 2.12 395 0 101 1.44
I have made a script like this but need to press enter to get the output .
$ for i in ` lparstat 2 10 | tail -10 | awk '{print $4}'`
> do
> read arr[$i]
> echo arr[$i]
> done
arr[94.0]
arr[97.7]
arr[94.9]
arr[91.0]
arr[98.1]
arr[97.7]
arr[93.0]
arr[94.8]
arr[97.9]
arr[89.2]
Your script only needs a small improvement to calculate the average. You can do that inside awk right away:
lparstat 2 10 | tail -n 10 | awk '{ sum += $4 } END { print sum / NR }'
The tail -n 10 takes 10 last lines.
{ sum += $4 } is calculated for each line - it sums the values at 4th column.
Then END block executes after the whole file is read. The { print sum / NR } prints the average. NR is "Number of Records", where one record is one line, so it's number of lines.
Notes:
backticks ` are discouraged. The modern $( ... ) syntax is much preferred.
The "for i in `cmd`" or more commonly for i in $(...) is a common antipattern in bash. Use while read -r line when reading lines from a command, like cmd | while read -r line; do echo "$line"; done or in bash while read -r line; do echo "$line"; done < <(cmd)

How assign a new terminal window to each child process

I want to fork multiple processes and assign each child process it's own terminal window so that IPC can be demonstrated easily.
Forking goes on fine, and if I run the child processes on the same terminal it runs fine.
However to make each child process have its own terminal window, I do
execl("/usr/bin/xterm", "xterm", "-e", "yourprogram", NULL);
The program runs in a new window, but its PID is different from that shown by the parent which forks the process. What am I doing wrong?
Thanks
edit1 - this is my main function (the parent process). I fork 4 child processes. I want each child process to have its own terminal window. However the child process just exits, and a new process with a different PID continues to run in the new terminal.
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/shm.h>
int main()
{
pid_t pid[4];
int i = 0;
int status;
//Fork four new processes
for(i=0; i<4; i++)
{
pid[i] = fork();
if(pid[i] == 0 && i == 0)
{
execl("/usr/bin/xterm", "xterm", "./child1", NULL);
exit(1);
}
else if(pid[i] == 0 && i == 1)
{
execl("/usr/bin/xterm", "xterm", "./child2", NULL);
exit(1);
}
else if(pid[i] == 0 && i == 2)
{
execl("/usr/bin/xterm", "xterm", "./child3", NULL);
exit(1);
}
else if(pid[i] == 0 && i == 3)
{
execl("/usr/bin/xterm", "xterm", "./child4", NULL);
exit(1);
}
else
{
//Parent process
printf("The main function has forked a process with pid: %d\n", pid[i]);
}
}
for(i=0;i<4;i++)
{
status = waitpid(pid[i], NULL, 0);
if(status == pid[i])
printf("%d: Process Terminated Successfully\n", pid[i]);
else
{
perror("waitpid");
exit(1);
}
}
return 1;
}
edit2 - added ps -u output:
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
dell-pc 3024 0.1 0.0 26872 5480 pts/0 Ss 16:54 0:00 bash
dell-pc 3038 0.0 0.0 4200 632 pts/0 S+ 16:54 0:00 ./main
dell-pc 3039 22.5 0.1 109240 11116 pts/0 S+ 16:54 0:01 xterm ./child1
dell-pc 3040 26.1 0.1 109240 11268 pts/0 R+ 16:54 0:02 xterm ./child2
dell-pc 3041 28.7 0.1 109240 11180 pts/0 S+ 16:54 0:02 xterm ./child3
dell-pc 3042 27.0 0.1 109240 11288 pts/0 S+ 16:54 0:02 xterm ./child4
dell-pc 3044 4.1 0.0 4200 648 pts/24 Ss+ 16:55 0:00 child3
dell-pc 3046 3.7 0.0 4200 680 pts/26 Ss+ 16:55 0:00 child4
dell-pc 3048 3.8 0.0 4200 792 pts/25 Ss+ 16:55 0:00 child2
dell-pc 3050 3.3 0.0 4200 660 pts/14 Ss+ 16:55 0:00 child1
dell-pc 3060 2.0 0.0 26816 5412 pts/27 Ss 16:55 0:00 bash
dell-pc 3072 0.0 0.0 22648 2688 pts/27 R+ 16:55 0:00 ps -u
edit3: added output of main:
The main function has forked a process with pid: 3491
The main function has forked a process with pid: 3492
The main function has forked a process with pid: 3493
The main function has forked a process with pid: 3494
3491: Process Terminated Successfully
3492: Process Terminated Successfully
3493: Process Terminated Successfully
3494: Process Terminated Successfully
I did a program like yours (naming it stackoverflow), executing vi in an xterm, and while it is running I open a third xterm to run ps -u. Output is:
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
osboxes 1713 0.0 0.2 6588 4756 pts/0 Ss 18:56 0:00 bash
osboxes 1780 0.0 0.2 6508 4484 pts/1 Ss 19:12 0:00 bash
osboxes 1836 88.4 0.0 2020 532 pts/0 R+ 19:21 0:29 ./stackoverflow
osboxes 1837 0.1 0.4 12844 8952 pts/0 S+ 19:21 0:00 /usr/bin/xterm -e vi stackoverflow.txt
osboxes 1839 0.0 0.1 6072 3536 pts/2 Ss+ 19:21 0:00 vi stackoverflow.txt
osboxes 1840 0.0 0.1 4772 2452 pts/1 R+ 19:22 0:00 ps -u
Output of program is:
PID=1836
child PID=1837
So the child is still running xtermcommand. It created another child running vi (pid 1839).
IPC Demo and sample using terminal windows, under bash
Because it's easy under bash:
This will require simple terminal tools, like xterm. This was successfully tested with lxterm, mate-terminal, konsole and gnome-terminal. Of course, tmux and screen must be able too...
Ok, let's go. We assume you're already in some terminal window, we will name this initial console.
1. First opening a display window:
So, from the initial console, open log window:
exec 5> >(xterm -T 'Log window...' -e sh -c "cat /proc/$$/fd/5")
or
exec 5> >(xterm -e sh -c "printf '\\e];Log window...\\a';cat /proc/$$/fd/5")
exec 5> >(konsole --nofork -e sh -c "cat /proc/$$/fd/5")
exec 5> >(lxterm -T "Log window..." -e sh -c "cat /proc/$$/fd/5")
exec 5> >(mate-terminal -t 'Log window...' -x sh -c "cat /proc/$$/fd/5")
exec 5> >(gnome-terminal --window -x sh -c "printf '\\e];Log window...\\a';cat /proc/$$/fd/5")
Variant usefull for debugging
exec 5> >(xterm -e sh -c "printf '\\e];Log window...\\a';
tee </proc/$$/fd/5 /dev/tty | sed -u s/.*/now/|date -f -")
Will print date and time on each line output.
exec 5> >(xterm -e sh -c "printf '\\e];Log window...\\a';
tee </proc/$$/fd/5 /dev/tty | sed -u s/.*/now/|date -f - ; read foo")
Same, but will keep window open after closing from parent, waiting for terminal input (Return) before closing (or close by window manager).
2. Testing, then using this:
Always in initial console, hit:
echo >&5 This is a test string.
This must prompt in Log window.
Ok, now:
xterm -T 'Input window' -e bash --rcfile <(echo "exec 1>/proc/$$/fd/5") &
Note: There, double-quotes will ensure $$ will expand from initial window's shell level.
So now, you could enter command in Input window and read results on Log window.
3. Closing window
Window will close when file descriptor is closed:
exec 5>&-
Full script using 3 window
You may found full script there:
ipc_win-demo.sh.txt
ipc_win-demo.sh
For gnome terminal I used:
execl("/usr/bin/gnome-terminal", "gnome-terminal", "-q", "-e", "./my_binary", (char*)0);

Please explain the ps -aef response on RHEL

What does pts/2 indicate in the below output. Why there is no such for other dd processes?
$ ps -aef |grep dd
root 6553672 15073352 3 02:32:19 - 0:01 dd of=/dev/lv01 bs=1024k
padmin 9437410 16515110 1 02:43:32 **pts/2** 0:00 grep dd
root 13828156 11010220 0 02:32:33 - 0:00 dd of=/dev/lv02 bs=1024k
root 14155860 13828156 2 02:32:33 - 0:01 dd of=/dev/lv02 bs=1024k
root 15073352 13762812 0 02:32:19 - 0:00 dd of=/dev/lv01 bs=1024k
root 15532200 15925276 2 02:40:47 **pts/1** 0:03 dd of=/home/padmin/sample-dd-op bs=1024k
pts/X in the TTY column means that the process is connected to a pseudo terminal slave.
An empty value means:
The terminal session has ended
The command was fired by a daemon
This nice Answer shows the difference between PTS and TTY.

fork() and kill in linux

In my project, I need a sub-task to play in parallel with a parent task. I use fork() to create a parallel process which is aplay xyz.wav. Now when I want to kill the child process from the parent process e.g system("kill -9 aplay ") the aplay is killed, but I see two instances of the parent task. I think one of them is a copy made by the call to fork() and the other one is the original. And with each fork() call, the number of copies increases. I am conscious about memory overflow. I just want to keep the original process. I have tried to kill that parent copy but failed!copies of the parent process appear as 'defunct'.
the 'defucnt' process continue to increase as i call parallel process, whether i kill aplay or not. I also tried to kill defunt by its PID, it also didn't work.
static int
test(Core *pc, char *args)
{
pid1=fork();
if (pid1 ==0)
{
system ("ps " );
system("aplay /opt/Line_Tone_14s.wav");
_exit(0);
}
else if(pid1<0)
{
out("fork() ERROR (-1) returned\n");
}
else if(pid1>0)
{
out("I AM IN PARENT PROCESS() NOW\n");
}
return 1;
}
static int
test1(Core *pc, char *args)
{
system ("ps " );
system ("killall -9 aplay ");
return 1;
}
Initially
> PID TTY TIME CMD
1580 pts/0 00:00:00 sudo
1581 pts/0 00:00:00 su
1589 pts/0 00:00:00 bash
5732 pts/0 00:00:00 parent
5738 pts/0 00:00:00 sh
5739 pts/0 00:00:00 ps
>test
> PID TTY TIME CMD
1580 pts/0 00:00:00 sudo
1581 pts/0 00:00:00 su
1589 pts/0 00:00:00 bash
5732 pts/0 00:00:00 parent
5737 pts/0 00:00:00 parent
5740 pts/0 00:00:00 sh
5741 pts/0 00:00:00 aplay
5743 pts/0 00:00:00 sh
5744 pts/0 00:00:00 ps
>test1
>killed
after kill
>PID TTY TIME CMD
1580 pts/0 00:00:00 sudo
1581 pts/0 00:00:00 su
1589 pts/0 00:00:00 bash
5732 pts/0 00:00:00 parent
5737 pts/0 00:00:00 parent <defunct>
5753 pts/0 00:00:00 sh
5754 pts/0 00:00:00 ps
>test
> PID TTY TIME CMD
1580 pts/0 00:00:00 sudo
1581 pts/0 00:00:00 su
1589 pts/0 00:00:00 bash
5732 pts/0 00:00:00 parent
5737 pts/0 00:00:00 parent <defunct>
5759 pts/0 00:00:00 parent
5762 pts/0 00:00:00 sh
5763 pts/0 00:00:00 aplay
5765 pts/0 00:00:00 sh
5766 pts/0 00:00:00 ps
>test1
>killed
after kill
>PID TTY TIME CMD
1580 pts/0 00:00:00 sudo
1581 pts/0 00:00:00 su
1589 pts/0 00:00:00 bash
5732 pts/0 00:00:00 parent
5737 pts/0 00:00:00 parent <defunct>
5759 pts/0 00:00:00 parent <defunct>
5773 pts/0 00:00:00 sh
5774 pts/0 00:00:00 ps
i also tried with this in test() command
else if(pid1>0)
{
out("I AM IN PARENT PROCESS() NOW\n");
wait(&status);
}
by doing this only one parent process remain after aplay finishes to play sound, no matter how many times i call the "test" command. but the issue with this is that, I can not type any other command during sound play, until it finishes. so could not kill it in between playing the sound.
I want to play sound in parallel, and want to kill any time i want.
Don't kill it that way! You have the child PID in pid1, just use the kill() function to kill it.
Spawning an separate process to run killall is unnecessary, expensive and (as you've found out), not that reliable. What if there are five copies of that executable running?
You can use something like:
#include <sys/types.h>
#include <signal.h>
:
int rc = kill (pid1, 9); // or SIGKILL for portability, rather than 9.
// Check rc and errno.
in your parent.
I would also seriously look into removing the system calls in the child process as well since they start up separate processes. You can do better by using the exec family of calls the replace the program in the child's process space.

Resources