Problems with accessing job PID in LINUX shellscript - linux

if I run the expression
ps -fu $USER| grep 'mount' | grep -v 'grep' | awk '{print $2}'
in the command line, I get - as expected - the PID of the processes containing "mount" in their description.
I want to achieve the following to kill certain background processes programmatically. The following code in the shell script:
#!/usr/bin/env bash
mountcmd="ps -fu $USER| grep 'mount' | grep -v 'grep' | awk '{print $2}' "
mountpid=$(eval "$mountcmd")
echo "Found existing background job PID: " "$mountpid"
does not provide the PID, but the output of echo is:
Found existing background job PID: wgeithne 6284 1 0 17:09 pts/3 00:00:00 minikube mount /u/wgeithne/bin/grafana/config:/grafana
How do I get the only the PID as output of my script?

The stupid eval trick requires additional escaping of the dollar sign in the Awk script. But really, a massively superior solution is to avoid stupid eval tricks.
Perhaps see also https://mywiki.wooledge.org/BashFAQ/050
If you really need to reinvent pidof, probably get rid of the antipatterns.
mountpids=$(ps -fu "$USER" | awk '/[m]ount/ { print $2 }')

Related

Display the name of all running processes in Linux in a file using a bash script

I need to display the name of all running processes in Linux in a file using a bash script. I wrote the code, but didnt succeed:
#!/bin/bash
for i in `ps aux| awk '{print $5}'`;
echo $i > /tmp/test;
done
Need your assistance, Thanks.
Using the for, the syntax is slightly different:
#!/bin/sh
cat /dev/null > /tmp/test
for i in $(ps aux | awk '{print $5}'); do
echo $i >> /tmp/test;
done
You missed the do operator
The output redirector > on a loop should change to appending >>, otherwise only the last value of the loop will be saved.
But as #stark said, the for is not required:
#!/bin/sh
ps aux | awk '{print $5}' > /tmp/test;
I'm not sure, what your output should look like. With your template, and the fixes from Glauco Leme, I only got the VSZ of all the processes.
I assume you need the cmd of each process, then you just can use ps -e --no-headers --format cmd.
In case you need it in a file:
ps -e --no-headers --format cmd > /tmp/test
I hope this will do what you need.

Get a process ID

I read a lot of questions about this argument, but I can't solve my issue.
I need to get a specific process ID and I wrote the following test.sh script:
#!/bin/sh
PID=$(ps -ef | grep abc | grep -v grep | awk '{print $2}')
echo $PID
Running this script I get two different PIDs if the abc process is not running and three different PIDs if the abc process is running.
If I run the
ps -ef | grep abc | grep -v grep | awk '{print $2}'
command from shell I get the right result.
Modifing the test.sh script removing the last awk I noticed that the script prints the following output:
user1 22153 129551 0 15:56 pts/3 00:00:00 /bin/sh ./test.sh
user1 22155 22153 0 15:56 pts/3 00:00:00 /bin/sh ./test.sh
How is it possible and how can I ignore them?
If you know exactly what is the process called, use pidof, otherwise, you can just use pgrep, it saves your grep|grep|awk....
Note that, when you ps|grep regex or pgrep regex there could be multiple entries in your result.
Do not use these tools, use the right tool meant for this, command pidof with the POSIX compatible -s flag which according to the man page says,
-s Single shot - this instructs the program to only return one
pid.
Using the above,
processID=$(pidof -s "abc")
I am not a big fan of parsing the process table. It could be inaccurate. For the same reason as "why not parse ls" You may want to look at the command pgrep
My suggestion is doing
pgrep -u user1 abc

Error displaying info with an script

I need to display certain info trough the terminal using a bash script.
The info i need to display is UID, PID, PPID, STATUS, CMD.
Okay, so i kind of did that already but i have certain issues with the identation and the printing.
I need to display it this way:
UID PID PPID STATUS CMD
root 1 0 Sleeping /sbin/init
But with my code i get this:
UID PID PPID STATUS CMD
root
1 0 (sleeping) /sbin/init
This is my code actually:
echo "UID PID PPID STATUS CMD"
for i in /proc/*; do
getent passwd `cat $i/status|grep "^Uid"`| cut -d: -f1|head -1
cat $i/status|grep "^Pid"|awk '{printf "%-9s",$2}'
cat $i/status|grep "^PPid"|awk '{printf "%-9s",$2}'
cat $i/status|grep "^State"|awk '{printf"%-9s",$3}'
cat $i/cmdline|awk '{printf " %-25s",$1}'
echo '\n'
done
With this code i also get a lot of "not a directory" errors.
I'm new at this so i need tons of help :(
note: i can't use ps command
The command ps (check man ps) could do all that all by itself:
$ ps -eo user,pid,ppid,state,cmd | head -n 10
The only problem is that head outputs a full line, but you want to suppress the newline. Do that by capturing the output and displaying it with printf.
The below also cleans up the more egregious uses of useless cat and grep, but could be simplified further.
echo "UID PID PPID STATUS CMD"
for i in /proc/*; do
uid=$(getent passwd $(grep "^Uid" "$i/status") | cut -d: -f1 | head -1)
printf '%-9s' "$uid" # May need to adjust the formatting
awk '/^Pid/ {printf "%-9s",$2}' "$i/status"
awk '/^PPid/ {printf "%-9s",$2}' "$i/status"
awk '/^State/ {printf"%-9s",$3}' "$i/status"
awk '{printf " %-25s\n",$1}' "$i/cmdline"
done
If you want to play with shell, first read docs :
FAQ http://mywiki.wooledge.org/BashFAQ
Guide: http://mywiki.wooledge.org/BashGuide
Ref: http://gnu.org/s/bash/manual
Then to display what you need without any mess :
ps -c -o 'uid pid ppid status ucmd'

Awk not working inside bash script

Im trying to write a bash script and trying to take input from user and executing a kill command to stop a specific tomcat.
...
read user_input
if [ "$user_input" = "2" ]
then
ps -ef | grep "search-tomcat" |awk {'"'"'print $2'"'"'}| xargs kill -9
echo "Search Tomcat Shut Down"
fi
...
I have confirmed that the line
ps -ef | grep "search-tomcat"
works fine in script but:
ps -ef | grep "search-tomcat" |awk {'"'"'print $2'"'"'}
doesnt yield any results in script, but gives desired output in terminal, so there has to be some problem with awk command
xargs can be tricky - Try:
kill -9 $(ps -ef | awk '/search-tomcat/ {print $2}')
If you prefer using xargs then check man page for options for your target OS (i.e. xargs -n.)
Also noting that 'kill -9' is a non-graceful process exit mechanism (i.e. possible file corruption, other strangeness) so I suggest only using as a last resort...
:)

How do I get "awk" to work correctly within a "su -c" command?

I'm running a script at the end of a Jenkins build to restart Tomcat. Tomcat's shutdown.sh script is widely known not to work all in many instances and so my script is supposed to capture the PID of the Tomcat process and then attempt to manually shut it down. Here is the command I'm using to capture the PID:
ps -ef | grep Bootstrap | grep -v grep | awk '{print $2}' > tomcat.pid
The output when manually runs retrieves the PID perfectly. During the Jenkins build I have to switch users to run the command. I'm using "su user -c 'commands'" like this:
su user -c "ps -ef | grep Bootstrap | grep -v grep | awk '{print $2}' > tomcat.pid"
Whenever I do this however, the "awk" portion doesn't seem to be working. Instead of just retrieving the PID, it's capturing the entire process information. Why is this? How can I fix the command?
The issue is that $2 is being processed by the original shell before being sent to the new user. Since the value of $2 in the shell is blank, the awk command at the target shell essentially becomes awk {print }. To fix it, you just escape the $2:
su user -c "pushd $TOMCAT_HOME;ps -ef | grep Bootstrap | grep -v grep | awk '{print \$2}' > $TOMCAT_HOME/bin/tomcat.pid"
Note that you want the $TOMCAT_HOME to be processed by the original shell so that it's value is set properly.
You don't need the pushd command as you can replace the awk command with:
cut -d\ -f2
Note: two 2 spaces between -d\ and -f2

Resources