Linux CLI watch
command has a switch -e
, --errexit
that has a description:
Freeze updates on command error, and exit after a key press.
That switch should make watch stop executing command if it returned non zero exit code.
The problem is that watch
terminates if the output of command does not fit into the CLI window. The problem is present sometimes when the CLI window is full screen on Ubuntu 18.04 and always when you resize window or it is smaller than full screen.
An example of script having commands:
task.sh
#!/bin/sh
for i in $(seq 1 200)
do
printf "Task #${i}\n";
done
exit 0;
and watch command:
watch -e -n 1 ./task.sh;
watch unexpected error:
command exit with a non-zero status, press a key to exit
How to solve that problem? I can't redirect standard output to /dev/null
because at least partial output of the commands that are executed with watch
needs to be printed and watch should terminate if any command of the executed script returns non zero exit code so I guess I'm forced to use -e
, --errexit
switch.
If there is no good solution to that specific watch
behavior, is there any good replacement for watch
?
EDIT
It looks like watch
problem is rather related to multiple commands print exceeding visible terminal output than the the total of printed string. This example uses single printf
and does not have any problem when resizing terminal screen even it prints more than the visible part of the terminal:
#!/bin/sh
output="";
for i in $(seq 1 200)
do
output="${output}$(printf "Task #${i}")\n";
done
printf "$output";
exit 0;
but this hack can work with relative small scripts, I can't imagine using watch and doing this workaround for every command inside task.sh srcipt
Another workaround:
#!/usr/bin/env bash
temp="$(mktemp /tmp/watch.XXXXXXX)"
exec 3>&1; exec > $temp
date # for demo purpose
for i in $(seq 1 200)
do
printf "Task #${i}\n";
done
exec 1>&3
cat $temp; rm $temp
So you don't need to change much the original bash script.
I cannot think of way using variable, if tmp file is really an issue, try this:
#!/usr/bin/env bash
{
date # for demo purpose
for i in $(seq 1 200)
do
printf "Task #${i}\n";
done
} | head -n $LINES
Task wrapper for watch
with -e
switch (exit on error).
Does not have any problem when resizing terminal window, even down to just 1 line.
Optionally may save stdout
and stderr
into a file.
Works as #!/bin/bash
or #!/bin/sh
task-wrapper.sh
#!/bin/sh
# path to file where to put stdout and stderr on error
error_log="$1";
output="$(
# exit sub shell with non zero code on
# any line in sub shell having non zero exit code
set -e;
{
# ========== Commands Block =============
# uncomment below to simulate an error
# ls /this/is/non/existing/path;
# an example of lot of print exceeding
# count of displayed terminal lines
for i in $(seq 1 200)
do
printf "Task #${i}\n";
done
# uncomment below to simulate an error
# ls /this/is/non/existing/path;
# ========== Commands Block =============
} 2>&1;
)";
# get sub shell exit code
# print output (limit to terminal capacity)
# save error if any
# exit with error code if any
# or exit 0;
ec="$?"; if [ $ec -eq 0 ]; then
# zero exit code
# prevent echo if there are only two
# lines of terminal available because
# they may be already consumed by watch
# and its status if watch run without
# --no-title switch (default)
if [ $LINES -gt 2 ]; then
echo "$output" | tail -n "$(($LINES - 2))";
fi;
exit 0;
else
# non zero exit code
# watch on error
# consumes additional one line
# therefore don't echo if lines
# available are less than 4
if [ "$LINES" -gt 3 ]; then
echo "$output" | tail -n "$(($LINES - 3))";
fi;
# watch erases terminal
# output after press of any key
# and its teminal print has no scroll
# so save whole stdout and stderr to file
# if path to it was provided
if [ -n "$error_log" ]; then
echo "$output" > "$error_log";
fi;
# exit with sub shell exit code
exit "$ec";
fi;
Usage:
watch -e ./task-wrapper.sh
Usage with path to file created as error log
watch -e ./task-wrapper.sh ./task-error.log
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.