Stopping a script process with a Control + C or something

14,093

Solution 1

Your pipeline

ps -aux | grep sox | kill 0

will not do what you want to do. This is because kill won't ever read the input from grep (the result from grep will also contain a lot of other things than just the PID of the sox process).

If you have pkill, just do

pkill sox

instead (use pkill -INT sox to send the same signal as Ctrl+C does).

If you change your startup script to

#!/bin/bash

NOW=$( date '+%F_%H:%M:%S' )

filename="/home/pi/gets/$NOW.wav"
sox -t alsa plughw:1  "$NOW.wav" & sox_pid="$!"

printf 'sox pid is %d\n' "$sox_pid"

wait

# Alternatively (instead of "wait", if you want to kill sox after six seconds):
# sleep 6 && kill "$sox_pid" 

echo "$filename"

You will get the PID of the sox process printed to the terminal and you could use that to do kill pid (with pid replaced by that number).

Using & ofte the sox invocation places it in the background. The PID of that background task is automatically stored in $! and the code above assigns it to sox_pid which is later printed.

The wait command waits for the sox command (running in the background) to finish.


As we discussed in a previous session: Double-quote all variable expansions.

Solution 2

use trapping:

#!/bin/bash

# this is a trap for ctrl + c 
trap ctrl_c INT

function ctrl_c() 
{
  echo "Trap: CTRL+C received, exit"
  exit
}
Share:
14,093

Related videos on Youtube

Reckless Liberty
Author by

Reckless Liberty

Updated on September 18, 2022

Comments

  • Reckless Liberty
    Reckless Liberty over 1 year

    I am trying to make an AV bug raspberry pi for a class.

    I am using sox to record sound. Which is working fine.

    the issue is sox needs to be stopped by a control+C to stop and create the new file. If killall is sent from a different ssh session it will drop the other session and sox will not create the file.

    listen.sh

    #! /bin/bash
    NOW=$( date '+%F_%H:%M:%S' )
    
    filename="/home/pi/gets/$NOW.wav"
    
    sox -t alsa plughw:1  $NOW.wav;
    
    sleep 6;
    
    echo $filename
    

    I have tried making a separate script for stopping it; pretty much

    killlisten.sh

    #! /bin/bash
    sleep 5;
    ps | grep sox | kill 0;
    

    Then run a

    superscript.sh

    #! /bin/bash
    ./listen.sh;
    ./killlisten.sh;
    

    Any advice on how to stop sox in a way that would still produce an output file would be great. This will ideally be set to run at set times so avoiding human interaction is essential.

  • Reckless Liberty
    Reckless Liberty over 6 years
    Awesome, thank you for the great explanation as well as the solution!
  • Reckless Liberty
    Reckless Liberty over 6 years
    for: printf 'sox pid is %d\n' "$sox_pid" Did you %d to ensure that the PID was inputted as an integer? Why not use %s? Just trying to learn, thank you.
  • Reckless Liberty
    Reckless Liberty over 6 years
    Error IDing, nice. The & after the sox is so BASH will create the $sox_pid? and printf? so sox needs to be in the bg for the rest of the script to work?
  • Kusalananda
    Kusalananda over 6 years
    @RecklessLiberty The & starts the given command as a background task, which gives control back to the script immediately. The PID of the command is then available in $!. The printf is solely for the user, in case they would want to kill the job manually with kill so that they know what PID to kill (it's not strictly needed).
  • Reckless Liberty
    Reckless Liberty over 4 years
    I didn't even know i could nest commands in a variable's parameters. Very cool.