Bash

Bash AliasingBash ArithmeticBash ArraysBash Associative arraysBash Avoiding date using printfBash Brace ExpansionBash Case statementBash CGI ScriptsBash Chain of commands and operationsBash Change shellBash co-processesBash Color script output (cross-platform)Bash Conditional ExpressionsBash Control StructuresBash Copying (cp)Bash Creating directoriesBash Customizing PS1Bash Cut CommandBash DebuggingBash Decoding URLBash Design PatternsBash File execution sequenceBash File Transfer using scpBash FindBash FunctionsBash getopts : smart positional-parameter parsingBash global and local variablesBash GrepBash Handling the system promptBash Here documents and here stringsBash history substitutionsBash Internal variablesBash IntroductionBash Job ControlBash Jobs and ProcessesBash Jobs at specific timesBash Keyboard shortcutsBash Listing FilesBash Managing PATH environment variableBash MathBash NamespaceBash Navigating directoriesBash on Windows 10Bash ParallelBash Parameter ExpansionBash Pattern matching and regular expressionsBash PipelinesBash PitfallsBash Process substitutionBash Programmable completionBash QuotingBash Read a file (data stream, variable) line-by-line (and/or field-by-field)Bash RedirectionBash ScopingBash Script shebangBash Scripting with ParametersBash Select keywordBash Sleep utilityBash SourcingBash Splitting FilesBash straceBash the cut commandBash true, false and : commandsBash Type of ShellsBash Typing variablesBash Using catBash Using sortBash Using trap to react to signals and system eventsBash when to use evalBash Word splittingNetworking with Bash



Bash Using trap to react to signals and system events

From WikiOD

Syntax[edit | edit source]

  • trap action sigspec... # Run "action" on a list of signals
  • trap sigspec... # Omitting action resets traps for signals

Parameters[edit | edit source]

Parameter Meaning
-p List currently installed traps
-l List signal names and corresponding numbers

Remarks[edit | edit source]

The trap utility is a special shell built-in. It's defined in POSIX, but bash adds some useful extensions as well.

Examples that are POSIX-compatible start with #!/bin/sh, and examples that start with #!/bin/bash use a bash extension.

The signals can either be a signal number, a signal name (without the SIG prefix), or the special keyword EXIT.

Those guaranteed by POSIX are:

Number Name Notes
0 EXIT Always run on shell exit, regardless of exit code
1 SIGHUP
2 SIGINT This is what ^C sends
3 SIGQUIT
6 SIGABRT
9 SIGKILL
14 SIGALRM
15 SIGTERM This is what kill sends by default

Introduction: clean up temporary files[edit | edit source]

You can use the trap command to "trap" signals; this is the shell equivalent of the signal() or sigaction() call in C and most other programming languages to catch signals.

One of the most common uses of trap is to clean up temporary files on both an expected and unexpected exit.

Unfortunately not enough shell scripts do this :-(

#!/bin/sh

# Make a cleanup function
cleanup() {
  rm --force -- "${tmp}"
}

# Trap the special "EXIT" group, which is always run when the shell exits.
trap cleanup EXIT

# Create a temporary file
tmp="$(mktemp -p /tmp tmpfileXXXXXXX)"

echo "Hello, world!" >> "${tmp}"

# No rm -f "$tmp" needed. The advantage of using EXIT is that it still works
# even if there was an error or if you used exit.

Catching SIGINT or Ctl+C[edit | edit source]

The trap is reset for subshells, so the sleep will still act on the SIGINT signal sent by ^C (usually by quitting), but the parent process (i.e. the shell script) won't.

#!/bin/sh

# Run a command on signal 2 (SIGINT, which is what ^C sends)
sigint() {
    echo "Killed subshell!"
}
trap sigint INT

# Or use the no-op command for no output
#trap : INT

# This will be killed on the first ^C
echo "Sleeping..."
sleep 500

echo "Sleeping..."
sleep 500

And a variant which still allows you to quit the main program by pressing ^C twice in a second:

last=0
allow_quit() {
    [ $(date +%s) -lt $(( $last + 1 )) ] && exit
    echo "Press ^C twice in a row to quit"
    last=$(date +%s)
}
trap allow_quit INT

Accumulate a list of trap work to run at exit.[edit | edit source]

Have you ever forgotten to add a trap to clean up a temporary file or do other work at exit?

Have you ever set one trap which canceled another?

This code makes it easy to add things to be done on exit one item at a time, rather than having one large trap statement somewhere in your code, which may be easy to forget.

# on_exit and add_on_exit
# Usage:
#   add_on_exit rm -f /tmp/foo
#   add_on_exit echo "I am exiting"
#   tempfile=$(mktemp)
#   add_on_exit rm -f "$tempfile"
# Based on http://www.linuxjournal.com/content/use-bash-trap-statement-cleanup-temporary-files
function on_exit()
{
    for i in "${on_exit_items[@]}"
    do
        eval $i
    done
}
function add_on_exit()
{
    local n=${#on_exit_items[*]}
    on_exit_items[$n]="$*"
    if [[ $n -eq 0 ]]; then
        trap on_exit EXIT
    fi
}

Killing Child Processes on Exit[edit | edit source]

Trap expressions don't have to be individual functions or programs, they can be more complex expressions as well.

By combining jobs -p and kill, we can kill all spawned child processes of the shell on exit:

trap 'jobs -p | xargs kill' EXIT

react on change of terminals window size[edit | edit source]

There is a signal WINCH ( WINdowCHange), which is fired when one resizes a terminal window.

declare -x rows cols

update_size(){
  rows=$(tput lines) # get actual lines of term
  cols=$(tput cols)  # get actual columns of term
  echo DEBUG terminal window has no $rows lines and is $cols characters wide
}

trap update_size WINCH

Credit:Stack_Overflow_Documentation