1

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.

Stephen Kitt
  • 411,918
  • 54
  • 1,065
  • 1,164
Reckless Liberty
  • 113
  • 2
  • 2
  • 6

4 Answers4

2

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.

Kusalananda
  • 320,670
  • 36
  • 633
  • 936
  • Awesome, thank you for the great explanation as well as the solution! – Reckless Liberty Mar 07 '18 at 11:00
  • 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 Mar 08 '18 at 10:34
  • @RecklessLiberty No worries :-) I used `%d` because I'm assuming that `$sox_pid` is an integer. If it's not an integer (for whatever reason), then the statement will generate an error message that can easily be seen. You could obviously use `%s` for _everything_, but I personally tend to use more specific format specifiers if I _know_ that the thing I'm printing is of a particular type. – Kusalananda Mar 08 '18 at 10:42
  • 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? – Reckless Liberty Mar 08 '18 at 10:53
  • @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). – Kusalananda Mar 08 '18 at 11:09
1

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
}
karmax
  • 11
  • 1
0

kill -SIGINT <pid> is the usual equivalent to ^C.

L29Ah
  • 793
  • 5
  • 19
0

This is working fine :

#!/bin/sh
# This script will do exactly the same job of Ctrl^C for background process
# find the PID of running script

pid=$(ps -ef| grep <scriptname>)

echo ".... PSR Stats collection script PID:"+$pid +"is getting exited abruptly"

# exit the process 
kill -INT $pid
Thomas
  • 6,242
  • 8
  • 26
  • 32
Manas
  • 1