Bash – How to kill this process in bash

bashshellshell-script

I am trying to interface my homemade Raspberry Pi-powered arcade machine with a coin acceptor, and for that I:

  • use a shell script (named gameplay) which starts the game emulator (MAME) when a coin is inserted
  • (want to) kill the MAME process(s) when the time is up (decided by an Arduino interface connected to the RPi), and go back to the loop in the shell script to (sleep and) wait for coin again

all is well except that I can't seem to kill the MAME process.

enter image description here

Please see the photo for more details.
The first pstree shows the processes when a game is being played. And the second pstree is when time is up, and the "emulationstation" process has been killed by the gameplay shell script (by sudo killall emulationstation).

But the "mame" process is still there and the game can still be played. I have also tried "sudo killall mame" but it doesn't work.

I've been trying many ways but none works so far.

UPDATE AFTER SOME OF YOUR KIND COMMENTS

I found that all the processes in the branch can be killed, except for the "mame" process, no matter what I tried. The best killall effort always results in "mame" becoming a sub-branch of "init" as: "init–mame—5*[{mame}]". Running "sudo killall mame" here gives nothing – no error, no effect. Why can't I just kill this process? (and this is a process of the "pi" user).

Then I tried a more violent kill, as @Colin Ameigh suggested below: "killall -9 mame" after the "killall emulationstation". And it ALMOST works, only that something was screwed up in the "gameplay" script – the terminal becomes blank, and the INSERT COIN… text is no longer there (but except for this, it works as intended, I also don't remember noticing any zombie processes). Here is the content of the gameplay script:

while true
do

clear
echo INSERT COIN...

while [[ $(cat /sys/class/gpio/gpio4/value) == '0' ]]; do
    sleep 1
    done

echo STARTING GAME...

#start game as separate process
emulationstation &

while [[ $(cat /sys/class/gpio/gpio4/value) == '1' ]]; do
    sleep 1
    done

sudo killall emulationstation
#sudo killall mame
sudo killall -9 mame

done

Best Answer

For a more general approach to killing processes...

This command should show the process

pgrep -f runcommand.sh

Then either cut and paste the process ID

kill PROCESSID

or, if you're a little braver using pipes

pgrep -f runcommand.sh | xargs -I{} kill {}

If you don't have pgrep (for some reason), then you can replace the pgrep command with this monstrosity:

ps aux | grep "[r]uncommand.sh" | sed 's/\s\+/ /g' | cut -f 2 -d ' '

The "[r]uncommand.sh" part just ensures that grep doesn't find its own process ID as well.

If the kill command does not end the process, then you may need to send a "SIGKILL" signal instead. To do that just add -9 to the kill command.

Given your specific use case - perhaps the shell script could have a SIGHUP handler that kills the mame process (since it should have the process ID) leaving the script running and the arduino trigger just has to send a SIGHUP to the script instead (via this mechanism, kill can send SIGHUP with -1), which can then return to a loop waiting for the coin signal.

Related Question