how to fined a process started with nohup after closing terminal? - linux

I have to ssh to a server for running some codes that take a long time to finish. so I need to use nohup command.
I started multiple processes using the nohup command like this:
nohup julia test.jl > Output1.txt &
nohup julia test.jl > Output2.txt &
nohup julia test.jl > Output3.txt &
nohup julia test.jl > Output4.txt &
the problem is that I closed the terminal and when I opened another terminal
I couldn't get the process name and ID using jobs -l.
I tried using ps -p but it answers me for all of the above processes with the same answer julia.
my question is " how can I specify which process is which?" note that only Output file name is different in these processes.
and
"how can I prevent such a problem in the future?"
Thanks for your time and answer.

One way to distinguish between these processes are through there stdout redirections and there is no good way of doing that using ps command.
If you have pgrep installed, you can use that with a simple for loop to know which pid correspond to which output file. Something like the following,
for pid in $(pgrep julia);
do
echo -n "$pid: ";
readlink -f /proc/${pid}/fd/1;
done
/proc/${pid}/fd/1 represents the stdout for the process with pid. It's a symlink, so you need to use readlink to check the source.
Output:
12345: /path/to/output1.txt
12349: /path/to/output2.txt
12350: /path/to/output3.txt
Alternative way would be to use lsof -p $pid, but I find it a bit on the heavy side than what you want to achieve, but the output would be same.
for pid in $(pgrep julia);
do
lsof -p $pid | awk -v var=$pid '/1w/ {print var": "$9}';
done

To find the PIDs of such processes, you can use fuser
$ fuser /path/to/outputfile
or lsof
$ lsof | grep "outputfile"
In order to avoid such a situation in future, use GNU Screen on the server (https://linode.com/docs/networking/ssh/using-gnu-screen-to-manage-persistent-terminal-sessions/).

Related

Is there a safe way to kill a named python process from within Shell script?

Summary : Attempting to stop a python3 script safely from within shell.
I am able to kill my python3 script (called, 'getphotos.py) but am concerned that killing the process while a photo is being saved, may lead to a corrupted sd card.
Is this something I need to worry about? If so, is there a more suitable command that I could use and one that checks first if the actual script is running before quitting/exiting ?
#!/bin/bash
cd /home/pi
pgrep -f getphotos.py # will give you its pid
pkill -9 -f getphotos.py # kills the matching pid
date >> killit.txt
Try to see if there are any open handles to picture files:
(lsof -p $(pgrep -f getphotos.py) | grep -q jpg) || pkill -9 -f getphotos.py
This will kill the process only if lsof did not return any jpg files.

Access to a process in procfs by name from bash

I want access to the status.log file of some processes, from bash terminal, in a while loop and compare them. So since the PID are not static how can I gain access to their proc/PID files with their command names and not with PID?
Try to grep output from ps -A by name of the command and get PID from there
Assuming you have pgrep (which you should, it's part of procps), call pgrep -x somecmdname to get a list of PIDs matching that string. From there you can access the proc files as usual.
e.g.
for pid in `pgrep -x somecmd`; do
echo $pid #or do something more interesting
done
Try the command pidof:
$ pidof bash
14317 10465 7204 3514 3466
Then you can loop over the pids:
$ for pid in $(pidof bash); do echo "$pid" ; done
14317
10465
7204
3514
3466
You can use this way
Example:
sleep 1000 &
cd /proc/`pidof sleep`
Refer this link man pidof

How to get all of the processes' names of a shell script?

$cat t.sh
grep "12" test | wc -c
I want to know how many processes will be created when it runs.
I used
./t.sh;ps -aux | grep "t.sh"
but it didn't work because "./t.sh" had run over when ps was working.
How can I reach this goal?
Depends on the system you are running on. If you have strace you can trace all the fork system calls. problem is though that somesystems use fork, some vfork and some clone, you will have to experiment. On linux:
strace -c -f -evfork ./t.sh
should give you a summary. -c gives a count, -f means "follow" child processes, and -evfork means trace the vfork kernel call. The output goes to stderr, but you can redirect it to a file using the -o option (there are some neat tricks you can do if you specify a named pipe here).
Your mistake is the semicolon. It tells the shell to wait until t.sh finishes before running grep. Use ampersand instead to tell the shell to run t.sh in the background. Also instead of grep you'd be better off using pstree to see the list of processes spawned by your t.sh script like this:
$ ./t.sh & pstree $(pgrep t.sh)
you can try
./t.sh;ps -aux | grep -E "t.sh"
-E match exactly what you need and nothing else, I'm not on linux right now so I can't be sure, but there's something to do with that option

Shell script to get the process ID on Linux [duplicate]

This question already has answers here:
How to get pid given the process name
(4 answers)
Closed 5 years ago.
I want to write a shell script (.sh file) to get a given process id. What I'm trying to do here is once I get the process ID, I want to kill that process. I'm running on Ubuntu (Linux).
I was able to do it with a command like
ps -aux|grep ruby
kill -9 <pid>
but I'm not sure how to do it through a shell script.
Using grep on the results of ps is a bad idea in a script, since some proportion of the time it will also match the grep process you've just invoked. The command pgrep avoids this problem, so if you need to know the process ID, that's a better option. (Note that, of course, there may be many processes matched.)
However, in your example, you could just use the similar command pkill to kill all matching processes:
pkill ruby
Incidentally, you should be aware that using -9 is overkill (ho ho) in almost every case - there's some useful advice about that in the text of the "Useless Use of kill -9 form letter ":
No no no. Don't use kill -9.
It doesn't give the process a chance to cleanly:
shut down socket connections
clean up temp files
inform its children that it is going away
reset its terminal characteristics
and so on and so on and so on.
Generally, send 15, and wait a second or two, and if that doesn't
work, send 2, and if that doesn't work, send 1. If that doesn't,
REMOVE THE BINARY because the program is badly behaved!
Don't use kill -9. Don't bring out the combine harvester just to tidy
up the flower pot.
If you are going to use ps and grep then you should do it this way:
ps aux|grep r[u]by
Those square brackets will cause grep to skip the line for the grep command itself. So to use this in a script do:
output=`ps aux|grep r\[u\]by`
set -- $output
pid=$2
kill $pid
sleep 2
kill -9 $pid >/dev/null 2>&1
The backticks allow you to capture the output of a comand in a shell variable. The set -- parses the ps output into words, and $2 is the second word on the line which happens to be the pid. Then you send a TERM signal, wait a couple of seconds for ruby to to shut itself down, then kill it mercilessly if it still exists, but throw away any output because most of the time kill -9 will complain that the process is already dead.
I know that I have used this without the backslashes before the square brackets but just now I checked it on Ubuntu 12 and it seems to require them. This probably has something to do with bash's many options and the default config on different Linux distros. Hopefully the [ and ] will work anywhere but I no longer have access to the servers where I know that it worked without backslash so I cannot be sure.
One comment suggests grep-v and that is what I used to do, but then when I learned of the [] variant, I decided it was better to spawn one fewer process in the pipeline.
As a start there is no need to do a ps -aux | grep... The command pidof is far better to use. And almost never ever do kill -9 see here
to get the output from a command in bash, use something like
pid=$(pidof ruby)
or use pkill directly.
option -v is very important. It can exclude a grep expression itself
e.g.
ps -w | grep sshd | grep -v grep | awk '{print $1}' to get sshd id
This works in Cygwin but it should be effective in Linux as well.
ps -W | awk '/ruby/,NF=1' | xargs kill -f
or
ps -W | awk '$0~z,NF=1' z=ruby | xargs kill -f
Bash Pitfalls
You can use the command killall:
$ killall ruby
Its pretty simple.
Simply Run Any Program like this :- x= gedit & echo $! this will give you PID of this process.
then do this kill -9 $x
To kill the process in shell
getprocess=`ps -ef|grep servername`
#echo $getprocess
set $getprocess
pid=$2
#echo $pid
kill -9 $pid
If you already know the process then this will be useful:
PID=`ps -eaf | grep <process> | grep -v grep | awk '{print $2}'`
if [[ "" != "$PID" ]]; then
echo "killing $PID"
kill -9 $PID
fi

Killing process in Shell Script

I have a very simple problem: When I run a shell script I start a program which
runs in an infinite loop. After a while I wanna stop then this program before I can
it again with different parameters. The question is now how do I find out the pid of
the program when I execute it? Basically, I wanna do something like that:
echo "Executing app1 with param1"
./app1 param1 &
echo "Executing app1"
..do some other stuff
#kill somehow app1
echo "Execution of app1 finished!"
Thanks!
In most shells (including Bourne and C), the PID of the last subprocess you launched in the background will be stored in the special variable $!.
#!/bin/bash
./app1 &
PID=$!
# ...
kill $PID
There is some information here under the Special Variables section.
In bash $! expands to the PID of the last process started in the background. So you can do:
./app1 param1 &
APP1PID=$!
# ...
kill $APP1PID
if you want to find out the PID of a process, you can use ps:
[user#desktop ~]$ ps h -o pid -C app1
the parameter -o pid says that you only want the PID of the process, -C app1 specifies the name of the process you want to query, and the parameter h is used to suppress the header of the result table (without it, you'd see a "PID" header above the PID itself). not that if there's more than one process with the same name, all the PIDs will be shown.
if you want to kill that process, you might want to use:
[user#desktop ~]$ kill `ps h -o pid -C app1`
although killall is cleaner if you just want to do that (and if you don't mind killing all "app1" processes). you can also use head or tail if you want only the first or last PID, respectively.
and a tip for the fish users: %process is replaced with the PID of process. so, in fish, you could use:
user#desktop ~> kill %app1
you obtain the pid of app1 with
ps ux | awk '/app1/ && !/awk/ {print $2}'
and then you should be able to kill it....(however, if you've several instances of app1, you may kill'em all)
pidof app1
pkill -f app1
killall app1
I had a problem where the process I was killing was a python script and I had another script which was also running python. I did not want to kill python because of the other script.
I used awk to deal with this (let myscript be your python script):
kill ps -ef|grep 'python myscript.py'|awk '!/awk/ && !/grep/ {print $2}'
Might not be as efficient but I'd rather trade efficiency for versatility in a task like this.

Resources