45

Is there any way to set the process name of a shell script? This is needed for killing this script with the killall command.

Nakilon
  • 34,866
  • 14
  • 107
  • 142
dan
  • 1,067
  • 3
  • 11
  • 17

13 Answers13

32

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
Weboide
  • 1,112
  • 1
  • 11
  • 22
  • This does not appear to change the actual process name as reflected by `/proc/$PID/comm` but rather changes the command as displayed in `ps` and `top` – Xaser Jan 07 '22 at 17:52
3

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.

joar
  • 15,077
  • 1
  • 29
  • 54
Brian Clapper
  • 25,705
  • 7
  • 65
  • 65
3

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 $!

Abs
  • 56,052
  • 101
  • 275
  • 409
3

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.

3

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
sheridp
  • 1,386
  • 1
  • 11
  • 24
  • Thanks! I've been looking to rename what shows in the `CMD` column of `ps -u username` just so I can kill the appropriate process easier. But searching and killing via `pkill -f myscript.py` is much more convenient. – sc4s2cg Dec 05 '20 at 15:53
1

Include #![path to shell]

Example for path to shell -

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

Full example

#!/usr/bin/bash
Executer
  • 11
  • 2
0

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.

Norman Ramsey
  • 198,648
  • 61
  • 360
  • 533
0

%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}\) ")
slaxor
  • 531
  • 4
  • 8
0

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.

unifex
  • 165
  • 1
  • 6
0

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>...]
John Allsup
  • 1,072
  • 8
  • 9
0

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
Anton Samokat
  • 542
  • 1
  • 6
  • 15
-1

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.

VoteyDisciple
  • 37,319
  • 5
  • 97
  • 97
  • 6
    Not true. Try it. Create a file called "tst.sh", make it executable, have it do something like a "sleep 30", and fire it up. You'll note that the process name associated with it is "/bin/sh" or "/bin/bash" or whatever you put in the shebang line. – Brian Clapper Jun 19 '10 at 14:06
-1

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}"
MangeshBiradar
  • 3,820
  • 1
  • 23
  • 41