Get the username and the process ID of a process in bash - bash

I am writing a bash script where I need to find out the userID of a process. For an example let the process be bash itself.
I tried ps aux | grep ba[s]h but the following was returned:
1000 2745 0.0 0.1 28360 5440 pts/1 Ss 10:11 0:01 bash
I see the userID 1000 displayed, but I want the username.

This can happen if the username is longer than 8 characters (OR) id has no name. But, If you want the username in the ps output then try this,
ps -eo uname:20,pid,pcpu,pmem,sz,tty,stat,time,cmd | grep '[b]ash'

You can parse out the /proc entry if you are on Linux and if you just need a numeric pid (or are OK with it). Here is an example for the mysqld process:
grep -e '^Uid:' /proc/$(pidof mysqld)/status | cut -f 2

The shortest way I found so far ( $PID - ID of the process inspected):
ps -p $PID -o euid=

Here is an example for gedit process
grep -w Pid /proc/$(pidof gedit)/status | cut -f 2

Related

How to get the two lines(head+filtered content) as output with a simple command?

I want to get the head as in my output.
ps lax |head -n 1
F UID PID PPID PRI NI VSZ RSS WCHAN STAT TTY TIME COMMAND
And the filtered line:
ps lax |grep openbox |grep -v grep
0 1000 1608 1513 20 0 206408 20580 SyS_po S ? 0:00 openbox --config-file /home/debian9/.config/openbox/lxde-rc.xml
What i expect to get is as below two lines:
F UID PID PPID PRI NI VSZ RSS WCHAN STAT TTY TIME COMMAND
0 1000 1608 1513 20 0 206408 20580 SyS_po S ? 0:00 openbox --config-file /home/debian9/.config/openbox/lxde-rc.xml
How to get the two lines(head+filtered content) as output with a simple command?
For compound conditions you use awk, not grep:
ps lax | awk 'NR==1 || /[o]penbox/'
Note the idiomatic use of [o] in #Cyrus and my answers so that the regexp doesn't match on this command itself so you don't need to explicitly remove this command name from with regexp.
ps lax | grep -e '^F' -e '[o]penbox'
or
ps lax | grep '^F\|[o]penbox'
Ed's answer using awk plus the NR==1 condition is the best solution.
For completeness, let me show the use of tee and processs substitution with >(command).
For instance: to display current processes (with ps) other than bash while retaining the ps header line, use tee in the following way:
$ ps | tee >(sed -n 1p) >(sed 1d | grep -v bash) > /dev/null
PID PPID PGID WINPID TTY UID STIME COMMAND
5782 2514 3792 1940 cons2 1415878 12:21:38 /usr/bin/ps
9998 2 9708 9708 ? 1415878 12:38:41 /usr/bin/ssh-agent
$
Here tee redirects the output to two processes:
one to display the first line (first sed -n 1p),
then other that filters the first line (the other sed 1d) and does an additional filtering with grep.
Finally, to prevent tee from dumping the original ps output, stdout is redirected to /dev/null

how to extract the PID of a process by command line

I want to get the PID of a process namely "cron" by command line.
I tried the following script.
ps ax|grep 'cron'
but I am getting a part of a table,
1427 ? Ss 0:00 /usr/sbin/cron -f
24160 pts/5 S+ 0:00 grep --color=auto cron
How I extract the pid from this ?
The pgrep utility will return the process IDs for the currently running processes matching its argument:
$ pgrep cron
228
It may also be used to "grep for" things on the command line:
$ pgrep -f uerfale
69749
69752
$ pgrep -l -f uerfale
69749 slogin uerfale
69752 slogin: /home/kk/.ssh/sockets/uerfale-9022-kk.sock [mux] m
To kill a process by name, use pkill. It works in the same way as pgrep but will send a signal to the matched processes instead of outputting a process ID.
Just use pidof, rather to use other commands and apply post-processing actions on them.
$ pidof cron
22434
To make the command return only one PID pertaining to to the process, use the -s flag
-s
Single shot - this instructs the program to only return one pid.
Like this, for example:
ps -ef|grep 'cron'|grep -v grep|awk '{print $2}'
You can try this;
ps -o pid,sess,cmd afx | egrep "( |/)cron( -f)?$"
or
pstree -pas <cronPID>

bash: differing newline count when assigning result to variable [duplicate]

This question already has answers here:
Check number of running scripts using ps
(4 answers)
Closed 6 years ago.
let's say I want to see how many copies of a program are already running. I could do something like this:
ps ax | grep -c "$0"
that command by itself produces the expected result. BUT if I attempt to assign the output to a variable, it gets incremented by one! No matter how I try it:
var=$(ps ax | grep "$0" | sed -n '$=')
var=`ps ax | grep -c "$0"`
can someone please show me the right way to capture the correct output?
it would also be great to know why this is happening..
UPDATE
after the first response from #fedorqui I realize I wasn't clear enough. let me elaborate:
I am running all three commands above in the same bash script. When I run the first one, it prints out the number 2: the program itself and the grep process with that program as an argument. when I run those same commands within variable assignments, the number 3 is stored.
please note that I am using two different methods of counting lines, grep and sed. in both cases they return 3 instead of the correct answer, 2.
here is a consolidated example to try in a test.sh file:
echo -n "without assignment: "
ps ax | grep -c "$0"
var=$(ps ax | grep "$0" | sed -n '$=')
echo "using sed method: $var"
var=`ps ax | grep -c "$0"`
echo "using grep method: $var"
the results on my debian box:
without assignment: 2
using sed method: 3
using grep method: 3
the questions again: why is this happening, and how to prevent or work around?
Quoting Siegex:
Because the grep process itself is being returned by ps.
You can either of these:
"trick" grep to not match itself by surrounding one of the search
characters in a character class [ ] which doesn't change the
functionality:
Or, in this case,
Pipe to grep -v grep, so that the process doesn't match:
var=$(ps ax | grep -v grep | grep "$0")
See an example. Here we have a process sleep:
$ sleep 20 &
[1] 5602
If we check for it in the output of ps it appears twice!
$ ps -ef| grep sleep
me 5602 5433 0 09:49 pts/2 00:00:00 sleep 20
me 5607 5433 0 09:49 pts/2 00:00:00 grep --colour=auto sleep
So we can either use a character class:
$ ps -ef| grep [s]leep
me 5602 5433 0 09:49 pts/2 00:00:00 sleep 20
Or grep out the grep process:
$ ps -ef| grep sleep | grep -v grep
me 5602 5433 0 09:49 pts/2 00:00:00 sleep 20
Command substitution itself runs in a subshell so thats one bash process
your search for bash ($0) i.e. grep -c bash also ends up in the process table at that time so thats another process (grep) containing string bash. Note that, this might not show up in the process table at the time of running, depending on how busy your system is.
And you have two (or whatever) actual bash processes (sessions) running presumably are the rest
You can use a Regex trick to get rid of the false positive i.e. grep one from count:
ps ax | grep -c "[b]ash"
It would still count the subshell while doing command substitution:
var=$(ps ax | grep -c "[b]ash")
So you need to manually remove one from this count.
Example:
$ var=$(ps ax | grep -c "bash")
$ echo $var
4
$ var=$(ps ax | grep -c "[b]ash")
$ echo $var
3
Your command counts the grep command line too.
ps ax | grep -v grep | grep -c "$0"
should omit the grep from the count

Retrieving full command line (w/ pipes &c) from a running bash script

How can I get the complete line of code running in the bash in a script that is run from within this line?
ping -c 2 google.com & ping -c 2 aol.com | grep aol & sh myscript.sh
where I want to retrieve the complete upper line in myscript.sh somehow.
My current approach is:
ping -c 2 google.com & ping -c 2 aol.com | grep aol & ps -ef --sort=start_time
And then correlate the PPID and the start time of the process to get what was run.
UID PID PPID C STIME TTY TIME CMD
nm+ 2881 6599 0 12:09 pts/1 00:00:00 ping -c 2 google.com
nm+ 2882 6599 0 12:09 pts/1 00:00:00 ping -c 2 aol.com
nm+ 2883 6599 0 12:09 pts/1 00:00:00 grep --color=auto abc
nm+ 2884 6599 0 12:09 pts/1 00:00:00 ps -ef --sort=start_time
I dont like it since I am unable to say how the processes are connected (pipes or just parallel execution) and therefore its impossible to reconstruct the exact line that was run in the bash. Also it feels to hackish for the right way.
You can grep "pipe" from lsof and find the correlated commands from the pipe id for a process and find the process id and look for details for the correlated processes.
Assuming bash 4.0 or newer:
#!/usr/bin/env bash
exec 3>"$1"; shift
BASH_XTRACEFD=3 PS4=':$BASH_SOURCE:$LINENO:+'
set -x
source "$#"
...if saved as bash_trace, used as:
bash_trace logfile scriptname arg1 arg2 ...
...then, to look up the actual line number, one can use something like the following:
IFS=: read -r filename lineno _ < <(tail -n 1 logfile)
sed -e "${lineno}q;d" <"$filename"

Is there any way to find the pids of children of a program?

Is there any way to find the pid of children of a program ?
For example I'm starting pppoe connection using system program:
pon dsl-provider
The program will exit after establishing connection and will spawn a pppd needed for connection:
ps wx | grep pppd
882 ? S 0:01 /usr/sbin/pppd call dsl-provider
The thing is (I was doing that until now) that I don't want to grep in ps listing, I want an exact answer, and I need this in many circumstances (the above is only an example). How can I do that?
Try pstree with the -p option to show the process tree of a process and its children with pids appended:
$ pstree -p `pgrep pppd`
You can try this
# somehow get the PID of the parent (882 in your case)
PID=`ps wx | grep pppd | awk '{ print $1; }'`
# formatted output (includes the parent)
ps ax --format pid,ppid,command | grep $PID | grep -v grep
I'd use ps --ppid ORIGINAL_PROGRAMS_PID although it might not work if the original program exited.

Resources