开发者

How to set the process name of a shell script?

Is there any way to set the process name of a shell scr开发者_如何学Goipt? This is needed for killing this script with the killall command.


Here's a way to do it, it is a hack/workaround but it works pretty good. Feel free to tweak it to your needs, it certainly needs some checks on the symbolic link creation or using a tmp folder to avoid possible race conditions (if they are problematic in your case).

Demonstration

wrapper

#!/bin/bash
script="./dummy"
newname="./killme"

rm -iv "$newname"

ln -s "$script" "$newname"

exec "$newname" "$@"

dummy

#!/bin/bash
echo "I am $0"
echo "my params: $@"

ps aux | grep bash

echo "sleeping 10s... Kill me!"
sleep 10

Test it using:

chmod +x dummy wrapper
./wrapper some params

In another terminal, kill it using:

killall killme

Notes

Make sure you can write in your current folder (current working directory).

If your current command is:

/path/to/file -q --params somefile1 somefile2

Set the script variable in wrapper to /path/to/file (instead of ./dummy) and call wrapper like this:

./wrapper -q --params somefile1 somefile2


You can use the kill command on a PID so what you can do is run something in the background, get its ID and kill it

PID of last job run in background can be obtained using $!.

echo test & echo $!


You cannot do this reliably and portably, as far as I know. On some flavors of Unix, changing what's in argv[0] will do the job. I don't believe there's a way to do that in most shells, though.

Here are some references on the topic.

  • Howto change a UNIX process and child process name by modifying argv0
  • Is there a way to change the effective process name in Python?


This is an extremely old post. Pretty sure the original poster got his/her answer long ago. But for newcomers, thought I'd explain my own experience (after playing with bash for a half hour). If you start a script by script name w/ something like:

./script.sh

the process name listed by ps will be "bash" (on my system). However if you start a script by calling bash directly:

/bin/bash script.sh /bin/sh script.sh bash script.sh

you will end up with a process name that contains the name of the script. e.g.:

/bin/bash script.sh

results in a process name of the same name. This can be used to mark pids with a specific script name. And, this can be useful to (for example) use the kill command to stop all processes (by pid) that have a process name containing said script name.


You can all use the -f flag to pgrep/pkill which will search the entire command line rather than just the process name. E.g.

./script &
pkill -f script


Include #![path to shell]

Example for path to shell -

  1. /usr/bin/bash
  2. /bin/bash
  3. /bin/sh

Full example

#!/usr/bin/bash


On Linux at least, killall dvb works even though dvb is a shell script labelled with #!. The only trick is to make the script executable and invoke it by name, e.g.,

dvb watch abc write game7 from 9pm for 3:30

Running ps shows a process named

/usr/bin/lua5.1 dvb watch ...

but killall dvb takes it down.


%1, %2... also do an adequate job:

#!/bin/bash
# set -ex

sleep 101 &
FIRSTPID=$!
sleep 102 &
SECONDPID=$!

echo $(ps ax|grep "^\(${FIRSTPID}\|${SECONDPID}\) ")
kill %2
echo $(ps ax|grep "^\(${FIRSTPID}\|${SECONDPID}\) ")
sleep 1
kill %1
echo $(ps ax|grep "^\(${FIRSTPID}\|${SECONDPID}\) ")


I put these two lines at the start of my scripts so I do not have to retype the script name each time I revise the script. It won't take $0 of you put it after the first shebang. Maybe someone who actually knows can correct me but I believe this is because the script hasn't started until the second line so $0 doesn't exist until then:

#!/bin/bash 
#!/bin/bash ./$0

This should do it.


My solution uses a trivial python script, and the setproctitle package. For what it's worth:

#!/usr/bin/env python3
from sys import argv
from setproctitle import setproctitle
from subprocess import run
setproctitle(argv[1])
run(argv[2:])

Call it e.g. run-with-title and stick it in your path somewhere. Then use via

run-with-title <desired-title> <script-name> [<arg>...]


Run bash script with explicit call to bash (not just like ./test.sh). Process name will contain script in this case and can be found by script name. Or by explicit call to bash with full path as suggested in display_name_11011's answer:

bash test.sh                           # explicit bash mentioning
/bin/bash test.sh                      # or with full path to bash
ps aux | grep test.sh | grep -v grep   # searching PID by script name

If the first line in script (test.sh) explicitly specifies interpreter:

#!/bin/bash
echo 'test script'

then it can be called without explicit bash mentioning to create process with name '/bin/bash test.sh':

./test.sh
ps aux | grep test.sh | grep -v grep

Also as dirty workaround it is possible to copy and use bash with custom name:

sudo cp /usr/bin/bash /usr/bin/bash_with_other_name
/usr/bin/bash_with_other_name test.sh
ps aux | grep bash_with_other_name | grep -v grep


Erm... unless I'm misunderstanding the question, the name of a shell script is whatever you've named the file. If your script is named foo then killall foo will kill it.


We won't be able to find pid of the shell script using "ps -ef | grep {scriptName}" unless the name of script is overridden using shebang. Although all the running shell scripts come in response of "ps -ef | grep bash". But this will become trickier to identify the running process as there will be multiple bash processing running simultaneously.

So a better approach is to give an appropriate name to the shell script.

Edit the shell script file and use shebang (the very first line) to name the process e.g. #!/bin/bash /scriptName.sh

In this way we would be able to grep the process id of scriptName using

"ps -ef | grep {scriptName}"
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜