while in bash script - linux

I am making a bash script. the objective is:
execute a program wait some seconds reset the program and repeat the process.
I make 2 scripts but i don't know where is the error...
#!/bin/bash
while true;
do
seg=`date +%M`;
if [[ "$seg" -eq "30" ]];
then killall sox;
echo "reset";
fi
done
bash: error sintáctico cerca del elemento inesperado `;'
#!/bin/bash
while true;
do
nice -n-10 sox -q -V0 --multi-threaded -t alsa hw:2,0 -t alsa pcm.default &&
done
bash: error sintáctico cerca del elemento inesperado `done'

Issues with Script #1:
The ; notation is to run multiple commands on the same line, one after another. Bash syntax requires that while and do on separate lines (same with if ... and then, and separated by ; if on the same line. Command statements are not normally terminated with a ; char in bash.
Change your code from:
#!/bin/bash
while true;
do
seg=`date +%M`;
if [[ "$seg" -eq "30" ]];
then killall sox;
echo "reset";
fi
done
To:
#!/bin/bash
while true
do
seg=`date +%M`
if [[ "$seg" -eq "30" ]]; then
killall sox
echo "reset"
fi
done
Issues with Script #2:
& means to run the command as a background process. && is used for conditional command chaining, as in: "If the previous command before && succeeds, then run the next command after the &&"
Change from:
#!/bin/bash
while true;
do
nice -n-10 sox -q -V0 --multi-threaded -t alsa hw:2,0 -t alsa pcm.default &&
done
To:
#!/bin/bash
while true
do
nice -n-10 sox -q -V0 --multi-threaded -t alsa hw:2,0 -t alsa pcm.default &
done

Related

Why does autostart script on Linux not work

I got an auto start bash script, to start fluidsyth and aconnect command automatically after rebooting my linux system (RPI-3):
#!/bin/bash
(STOP=$((SECONDS+5))
until [[ $SECONDS -ge $STOP || $(ps -C fluidsynth -o stat=) =~ S ]]; do:; done &&
aconnect 20:0 128:0 &)
fluidsynth -a alsa -g 5 /usr/share/sounds/sf2/FluidR3_GM.sf2
When I run this script, it popped up with the following error:
./piano4.sh: line 4: syntax error near unexpected token `done'
./piano4.sh: line 4: `until [[ $SECONDS -ge $STOP || $(ps -C fluidsynth -o stat=) =~ S ]]; do:; done &&'
Till now I cannot solve this error. There are no ^M in the script (I already checked).
Can anyone help me to get it up and running?
Thanks
There are no ^M in the script (I already checked)
I found the answer by changing the script into:
#!/bin/bash (STOP=$((SECONDS+15)) until [[ $SECONDS -ge $STOP || $(ps -C fluidsynth -o stat=) =~ S ]]; do echo "" > /dev/null; done && aconnect 20:0 128:0 &) fluidsynth -a alsa -g 5 /usr/share/sounds/sf2/FluidR3_GM.sf2
Thanks

bash script porting issue related to script program

I am trying to port an existing bash script to Solaris and FreeBSD. It works fine on Fedora and Ubuntu.
This bash script uses the following set of commands to flush the output to the temporary file.
file=$(mktemp)
# record test_program output into a temp file
script -qfc "test_program arg1" "$file" </dev/null &
The script program does not have -qfc options on FreeBSD and Solaris. On Solaris and FreeBSD, script program only has -a option. I have done the following until now:
1) update to latest version of bash. This did not help.
2) Try to find out where exactly is the source code of "script" program is. I could not find it either.
Can somebody help me out here?
script is a standalone program, not part of the shell, and as you noticed, only the -a flag is available in all variants. The FreeBSD version supports something similar to -f (-F <file>) and doesn't need -c.
Here's an ugly but more portable solution:
buildsh() {
cat <<-!
#!/bin/sh
SHELL="$SHELL" exec \\
!
# Build quoted argument list
while [ $# != 0 ]; do echo "$1"; shift; done |
sed 's/'\''/'\'\\\\\'\''/g;s/^/'\''/;s/$/'\''/;!$s/$/ \\/'
}
# Build a shell script with the arguments and run it within `script`
record() {
local F t="$(mktemp)" f="$1"
shift
case "$(uname -s)" in
Linux) F=-f ;;
FreeBSD) F=-F ;;
esac
buildsh "$#" > "$t" &&
chmod 500 "$t" &&
SHELL="$t" script $F "$f" /dev/null
rm -f "$t"
sed -i '1d;$d' "$f" # Emulate -q
}
file=$(mktemp)
# record test_program output into a temp file
record "$file" test_program arg1 </dev/null &

PPSS shell script

I made a simple shell script to process mp3 files with SoX.
for f in ./*.mp3; do sox "$f" "${f%%.mp3}S.mp3" silence 1 0.02 1% -1 0.02 1%; done
The syntax should be like this:
sox in.wav out.wav silence 1 0.1 1% -1 0.1 1%
It will remove silence from the files I have in a folder, and create a new file with an "X" at the end (to distinguish from the original). I saved the script in my /bin folder and it works fine.
However, now I want to use it with PPSS, in order to run 8 instances in parallel. I cannot seem to get it working though, in the log file the error I keep getting is this error in the logs:
/usr/local/bin/ppss: line 2283: soxy.sh/Users/marw/Downloads/testfolder//ppss_dir/job_log/_Users_marw_Downloads_testfolder__10_audio_mp3: No such file or directory
Status: FAILURE
Total processing time (hh:mm:ss): 00:00:01
The PPSS syntax should be like this:
|P|P|S|S| Distributed Parallel Processing Shell Script 2.97
usage: /usr/local/bin/ppss [[ -d <sourcedir> | -f <sourcefile> ]] [[ -c '<command> "$ITEM"' ]]
[[ -C <configfile> ]] [[ -j ]] [[ -l <logfile> ]] [[ -p <# jobs> ]]
[[ -q ]] [[ -D <delay> ]] [[ -h ]] [[ --help ]] [[ -r ]] [[ --daemon ]]
Examples:
/usr/local/bin/ppss -d /dir/with/some/files -c 'gzip '
/usr/local/bin/ppss -d /dir/with/some/files -c 'cp "$ITEM" /tmp' -p 2
/usr/local/bin/ppss -f <file> -c 'wget -q -P /destination/directory "$ITEM"' -p 10
I'm new to shell scripting, forgive me if it's a stupid question. My OS is MacOS 10.11.5.
This is what I'm trying with PPSS:
ppss -d /Users/marw/Downloads/testfolder -c 'soxy.sh'
Maybe I have to write the my original script differently? It works fine without PPSS though.
EDIT:
I got a debug log here: http://pastebin.com/wak47rf8
The -c argument has to have a trailing space at the end. This works:
ppss -d /Users/marw/Downloads/testfolder -c 'soxy.sh '
Whereas this does not work:
ppss -d /Users/marw/Downloads/testfolder -c 'soxy.sh'
I got this from the PPSS wiki on Github:
The -c option specifies the command that will be executed by PPSS in
parallel for each file within the directory specified by -d. In this
example the command has a trailing space, which is necessary since the
command will expand to 'gzip example.tar' when executed. If the space
is omitted, an error will occur.

get return value of command run with script -c

Is there a way to capture the return value of a program run using script -c?
For example (in bash)
/bin/false; echo $? # outputs 1
/usr/bin/script -c "/bin/false" /dev/null; echo $?
# outputs 0 as script exited successfully.
I need to get the return value from /bin/false instead of from /usr/bin/script.. is this possible? I'm using script to trick a program into thinking it is running in a real tty even though it isn't... Thanks!
According to man script, using -e option will return the exit code of the child process.
-e, --return
Return the exit code of the child process.
Uses the same format as bash termination
on signal termination exit code is 128+n.
Here's some example.
$ /usr/bin/script -e -c "/bin/false" /dev/null; echo $?
1
$ /usr/bin/script -e -c "/bin/true" /dev/null; echo $?
0
$ /usr/bin/script -e -c "exit 123" /dev/null; echo $?
123

Terminating half of a pipe on Linux does not terminate the other half

I have a filewatch program:
#!/bin/sh
# On Linux, uses inotifywait -mre close_write, and on OS X uses fswatch.
set -e
[[ "$#" -ne 1 ]] && echo "args count" && exit 2
if [[ `uname` = "Linux" ]]; then
inotifywait -mcre close_write "$1" | sed 's/,".*",//'
elif [[ `uname` = "Darwin" ]]; then
# sed on OSX/BSD wants -l for line-buffering
fswatch "$1" | sed -l 's/^[a-f0-9]\{1,\} //'
fi
echo "fswatch: $$ exiting"
And a construct i'm trying to use from a script (and I am testing with it on the command line on CentOS now):
filewatch . | while read line; do echo "file $line has changed\!\!"; done &
So what I am hoping this does is it will let me process, one line at a time, the output of inotify, which of course sends out one line for each file it has detected a change on.
Now for my script to clean stuff up properly I need to be able to kill this whole backgrounded pipeline when the script exits.
So i run it and then if I run kill on either the first part of the pipe or the second part, the other part does not terminate.
So I think if I kill the while read line part (which should be sh (zsh in the case of running on the cmd line)) then filewatch should be receiving a SIGPIPE. Okay so I am not handling that, I guess it can keep running.
If I kill filewatch, though, it looks like zsh continues with its while read line. Why?

Resources