Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detecting program errors in bash scripts?

Tags:

bash

ffmpeg

I'm trying to write my first semi advanced bash script that will take input in the form of a filename referring to an avi video, send it to ffmpeg to convert to a mp4 (preserving the original name) and then hand it off to MP4Box.

The below is pretty much what I'm doing...

#!/usr/bin/bash
ffmpeg -i $0 -acodec libfaac -ab 128k -ac 2 -vcodec libx264 -vpre hq -crf 22 -threads 0 ($0).mp4
MP4Box -inter 500 ($0).mp4
  • Is there some sort of try/catch I can do for the first program invocation to make sure MP4Box gets workable input?
  • Should I even bother with error catching at all, should I instead rely on the programs themselves to do this for me?
like image 763
meder omuraliev Avatar asked Dec 08 '22 05:12

meder omuraliev


1 Answers

One quick way to make the execution of one program dependent on the success of another is to use &&. (the commands below are all pseudo-code)

first-cmd && second-cmd

In this case second-cmd will only be executed if first-cmd returns true.

Likewise, you can test for failure and take appropriate action using ||

bad-cmd || echo "failed"

You can combine them in various ways:

good-cmd && echo "succeeded" || echo "failed"

bad-cmd || {
    recovery-cmd || 
    echo "recovery failed && 
    echo "recovered"
} 

Of course, it's often clearer to use the special variable $? that others have noted.

You will often want to redirect error messages to /dev/null or capture them in a variable.

bad-cmd 2>/dev/null               # send error message to the bit bucket
var=$(good-cmd)                   # capture stdout
var=$(bad-cmd 2>&1)               # capture stdout and stderr
var=$(bad-cmd 2>&1 >/dev/null)    # capture only stderr

Then you can process the text of the error to obtain additional information for conditional action in your code.

See: Capture output in a variable and How can I redirect stderr to a pipe?

like image 52
Dennis Williamson Avatar answered Jan 02 '23 20:01

Dennis Williamson