Search code examples
linuxbashshellkilllinux-mint

How do I kill the 'play' process in my shell script?


I'm writing a script that notifies me and plays a sound when my laptop battery reaches 15% but the problem is, when you plug in the charger, the sound continues to play. How can I kill the play process from the sound.sh script, or even kill the entire sound.sh script from the batmon.sh script?

I want this to happen under the condition that the charger is plugged in. My entire script works, however, it seems that when the play process is executed it waits to finish that process before continuing with the rest of the script, so it seems that my best bet is to kill the sound.sh script from the batmon.sh script under the condition that the charger is plugged into the computer. How do I do this? (I'm running Linux Mint 17.1, in case that matters.)

Here is my script:

#!/bin/bash
#batmon.sh

while true
do

    PLUG=`acpi | awk {'print $3'}`

    while [ $PLUG = "Discharging," ]
    do
        BATSTAT=`acpi | cut -d , -f 2`
        if [ $BATSTAT = "15%" ]
        then
            sh sound.sh &
            xcowsay --time=10 "Plug that shit in!" | sleep 100
        else
            PLUG=`acpi | awk {'print $3'}`
        fi
    done
done

#!/bin/bash
#sound.sh

x=1
SOUND=`play -q /home/greg/Documents/deththeme.wav &`

while [ $x = 1 ]
do
    $SOUND
    SOUND_PID=$!

    PLUG=`acpi | awk {'print $3'}`

    if [ $PLUG = "Charging," ] || [ $PLUG = "Unknown," ]
    then
        Kill $SOUND_PID
    else
        :
    fi
done

Solution

  • I think what might be happening is...

    When you do,

    SOUND=`play -q /home/greg/Documents/deththeme.wav &`
    

    it executes play in the background and stores the stdout of that process into SOUND, which is "".

    This might demonstrate:

    #!/usr/bin/env bash
    
    SOUND=`play -q /tmp/wav.wav &`
    echo SOUND = "$SOUND"
    $SOUND
    

    Output:

    # ./sound.sh 
    SOUND = 
    

    For me, $! does not work on VAR=$(cmd). If you want to kill the process, it might look like:

    play -q /home/greg/Documents/deththeme.wav &
    PID="$!"
    ...
    kill "$PID"
    

    An alternative if you don't have the pid and know that only one play process will be executing is to use pkill play, which will find the process by name.

    Also, you can use sleep at the end of the loop and it might stop it from spinning so hard.

    Here is a slightly modified version of your code:

    #!/usr/bin/env bash
    
    SOUNDFILE="/home/greg/Documents/deththeme.wav"
    
    while true ; do
            PLUG=$(acpi | cut -d' ' -f3)
            if [ "$PLUG" = "Discharging," ] ; then
                    BATSTAT=$(acpi | cut -d, -f2)
                    if [ "$BATSTAT" = "15%" ] ; then
                            play -q "$SOUNDFILE" &
                            PID="$!"
                            xcowsay --time=10 "Plug that shit in!"
    
                            # spin until play subprocess is done executing
                            while ps -p "$PID" >/dev/null ; do
                                    PLUG=$(acpi | cut -d' ' -f3)
                                    if [ "$PLUG" = "Charging," ] || [ "$PLUG" = "Unknown," ] ; then
                                            kill "$PID"
                                            break
                                    fi
                            done
                   fi
            fi
    done