Shell script returning non zero value after killing process - bash

I am trying to kill a process using a shell script.Looks shell itself is getting killed in this process. Also I am seeing non zero return value of the script in terminal.
I am running it on Amazon Linux 2 with sudo.
#!/bin/bash
kill -9 $(ps -ef | grep myapp | grep -v grep | awk '{print $2}')
I am executing like:
sudo ./myscript.sh
"echo $?" after executing is returning 137 instead of zero. Can someone please help to understand what is going wrong.
Another observation:
if i directly run kill command in my terminal, i.e below command,
kill -9 $(ps -ef | grep myapp | grep -v grep | awk '{print $2}')
I see echo $? is returning zero.
Update:
Problem is solved. Name of process I am trying to kill is overlapping with name of my script. Hence grep is returning both the pid's. Both the process are getting killed. Also learnt that better way of doing this by using pkill or using pidof() to get pid.

If you want the exit code of your last-run command to be the exit code for the script, your script must end with exit $? as the last line. Any function before that must also end with the $? so the chain flows to that final line. Otherwise some other exit is taking place.
If the script is being killed along side the application or script you are trying to kill, then your ps and grep work is likely including both in the results. Look at the output of the ps and grep while the script is running. You could add a line prior to your kill line which just shows the output of the ps and greps so you can see what is actually getting killed.
Finally (and I don't think this is the case) if you are trying to end the script after the kill, manually run an exit (again likely using exit $? for the reason stated above) where appropriate within the script.
Hope that helps you get where you are going.

Related

Cron job won't start again after I stopped it?

I wrote a script to run constantly on startup. If for whatever reason the script were to fail, I wrote a second script to check if it has failed, and if so, run the first script again. I then set this second script as a cronjob to run every minute so that it is constantly checking if the first script is alive.
So to test this, I reboot my system. I can see in htop that the first script is running from start up as expected. Good. I kill the process to test the second script. Sure enough, the second script starts the first script again. Still good. I then kill this process, but the second script won't run again now. It still updates a txt file when I manually start the first script, but the second script just doesn't start the first script like it's supposed to. Is it because I killed the cronjob? Restarting the cron service doesn't fix anything though, so I don't know why my second script isn't running again at all.
First script:
#!/bin/bash
stamp=$(date +%Y%m%d-%H%M)
timeout 10d tcpdump -i eth0 -s 96 -z gzip -C 10 -w /home/user/Documents/${stamp}
Second script:
#!/bin/bash
echo "not running" > /home/working.txt
if (( $(ps -ef | grep -v grep | grep tcpdump.sh | wc -l) > 0 ))
then
echo "tcpdump is running!!!" > /home/working.txt
else
/usr/local/bin/tcpdump.sh start
fi
Any help?
You would probably be better off running a simple for loop as the main script, and that kicks off the tcpdump script in the background, so something like:
#!/bin/bash
while true; do
if ps -ef | grep -v grep | grep -q tcpdump; then
: tcpdump running OK
else
# tcpdump not running - start it off
nohup /usr/local/bin/firstscript.sh start &
fi
sleep 30
done
This checks that "tcpdump.sh" is in the output of the "ps -ef" command - if it is, then do nothing (note that you must have an actual command between the "then" and "else" - the ":" command, which just takes it s arguments and ignores them, is sufficient). If it isn't running, start the first script in the background. Then sleep 30 seconds and check again. (Yes, I could have inverted the test so that I didn't need an empty "then" arm, but it would have made the code less obvious)
You put this script as the one which starts at boot time.
Edit: Do you really want to check for "tcpdump.sh"? Is that what the first script is actually called? Assuming that you actually want to check for the tcpdump program, you could use:
if pgrep tcpdump; then

Kill command won't work correctly in bash script

I was running an ubuntu console, when I type the following command, all the processes would be perfectly killed.
kill -9 $(ps -ef | grep 'job1/' | grep -v grep| awk '{print $2}')
But when I was trying to use crontab to call a script routinely, things went wrong.
#!/bin/bash
pid=$(ps -ef | grep 'job1/' | grep -v grep | awk '{print $2}')
echo $pid
kill -9 $pid
# the following commands were never executed
sleep 5
/data/job1/tomcat8/bin/startup.sh
The result was just like this:
15432 15438
Killed
It seems to just killed the job, but won't execute the following commands. Any idea?
If you are going to make a script that kills things by PID then you need to be very careful that you kill the right things.
You already have grep -v grep to avoid killing the grep itself, but it seems that you have not put in anything to protect against the script killing itself. Since you know your own PID you could grep -v that, but what if you are 123 and one of the things you want to kill is 1234? Probably safer to go by script name.

Bash function to kill process

I made an alias for this function in order to kill processes in bash:
On my .bashrc file
kill_process(){
# $1 being a parameter for the process name
kill $(ps ax | grep "$1" | awk '{print $1}')
}
alias kill_process=kill_process
So, suppose I want to kill the meteor process:
Let's see all meteor processes:
ps aux | grep 'meteor' | awk '{print $2}'
21565
21602
21575
21546
Calling the kill_process function with the alias
kill_process meteor
bash: kill: (21612) - No such process
So, the kill_process function effectively terminates the meteor processes, but it's kill command looks for an inexistent pid. Notice the pid 21612 wasn't listed by ps aux | grep. Any ideas to improve the kill_process function to avoid this?
I think in your case the killall command would do what you want:
killall NAME
The standard way of killing processes by name is using killall, as Swoogan suggests in his answer.
As to your kill_process function, the grep expression that filters ps will match the very own grep process (you can see this running the pipeline without awk), but by the time kill is invoked, that process is no longer running. That's the message you see.
Each time you run the command, grep runs again with a new PID: that's the reason you can't find it on the list when you test it.
You could:
Run ps first, pipe it into a file or variable, then grep
Filter grep's PID out of the list
(Simpler) supress kill output:
kill $(...) 2>/dev/null

Using variables and multiple pips in bash?

I'm trying to finish up a maintenance script, and I'm getting caught up with the following line:
PUID=$(ps aux | grep $PID | grep -v $USER| cut -d' ' -f1)
I'm trying to pull a specific process ID ($PID) out of the ps aux command, (while ignoring the process the user just created with the same PID), then eliminate all but the user name of the process owner.
Currently, the command runs fine when run in the command line, however I've been having issues assigning it to the variable $PUID, or even just executing it as a command. Any advice?
EDIT:
I'm trying to get this figured out and I believe there is still a problem in passing the variable $PID, right now it's pulling from a file (which it does properly) using this line
PID=$(cat /nfs/pdx/home/komcconx/PID/current/pid)
and if I add an echo $PID it returns the proper pid.
when I run the command PUID=$(ps -p $PID -o uname=), I get an error saying "ERROR: Process ID list syntax error." and if I runn the command with a "1" in the place of $PID it properly returns "root"
any ideas?'
Final edit:
Found out the issue was the PID was being pulled from a DOS file, and I was trying to run the command with a DOS newline, this issue is closed!
If you only want the user name of a process you can use -o option:
PUID=$(ps -p $PID -o uname=);
echo $PUID

run command in bash and then exit without killing the command

I am attempting to run a couple commands in a bash script however it will hang up on my command waiting for it to complete (which it wont). this script is simply making sure its running.
#!/bin/bash
ps cax | grep python > /dev/null
if [ $? -eq 0 ]; then
echo "Process is running."
else
echo "Process is not running... Starting..."
python likebot.py
echo $(ps aux | grep python | grep -v color | awk {'print $2'})
fi
Once it gets to the python command it hangs up while the command is being executed. its not till i cntrl c before it gives the pid. is there anyway i can have it run this bash script and exit the bash script once the commands were run (without waiting for them to complete).
In general, if you want to execute a command and not wait for it, you can simply use & as the delimiter rather than ; or a newline. When doing so, the pid of that process is available to the shell in the special variable !. If you want to wait for that process to complete, you can use wait. If you do not wish to wait for it, then simply omit the wait. In your case:
python likebot.py & # Start command asynchronously
echo $! # echo the pid of the most recent asynchronous process
Since it looks like likebot should be always running you might want to consider 'nohup' as well, with a bare & the job is still a child of your login process and will die if that dies.

Resources