Bash Don't Capture Ssh Errors

Bash don't capture ssh errors

With bash.

# disable job control and enable lastpipe to run mapfile in current environment
set +m; shopt -s lastpipe

# feed array_files with the output of your ssh/find command
ssh ... | mapfile -t array_files

# returncode of first command in pipe (here ssh)
echo "${PIPESTATUS[0]}"

# content of array array_files
declare -p array_files

In a script job control is disabled by default.

Bash ignoring error for a particular command

The solution:

particular_script || true

Example:

$ cat /tmp/1.sh
particular_script()
{
false
}

set -e

echo one
particular_script || true
echo two
particular_script
echo three

$ bash /tmp/1.sh
one
two

three will be never printed.

Also, I want to add that when pipefail is on,
it is enough for shell to think that the entire pipe has non-zero exit code
when one of commands in the pipe has non-zero exit code (with pipefail off it must the last one).

$ set -o pipefail
$ false | true ; echo $?
1
$ set +o pipefail
$ false | true ; echo $?
0

SSH capture exit code of remote ssh commands

Okay. It seems that this was a mistake on my end, and everything is working correctly. I wasn't calling one of the commands correctly:

php "$RELEASE_DIR" artisan migrate --no-interaction --force

This fixes it:

php "$RELEASE_DIR/artisan" migrate --no-interaction --force

unable to capture stderr while performing openssh to a variable- perl

When an error occurs it is most likely not going to be in STDOUT, and if it is in STDERR you are not catching that. You need to get to the application's exit code, in the following way. (Given the update to the question which I only see now: See the end for how to get STDERR.)

After the capture method you want to examine $? for errors (see Net-OpenSSH). Unpack that to get to the exit code returned by what was actually run by $ssh, and then look in that application's docs to see what that code means

$exit_code = $?;
if ($exit_code) {
$app_exit = $exit_code >> 8;
warn "Error, bit-shift \$? --> $app_exit";
}

The code to investigate is $app_exit.

An example. I use zip in a project and occasionally catch the error of 3072 (that is the $?). When that's unpacked as above I get 12, which is zip's actual exit. I look up its docs and it nicely lists its exit codes and 12 means Nothing to update. That's the design decision for zip, to exit with 12 if it had no files to update in the archive. Then that exit gets packaged into a two-byte number (in the upper byte), and that is returned and so it is what I get in $?.

Failure modes in general, from system in Perl docs

if    ($? == -1) { warn "Failed to execute -- " }
elsif ($? & 127) {
$msg = sprintf("\tChild died with signal %d, %s coredump -- ",
($? & 127), ($? & 128) ? 'with' : 'without');
warn $msg;
} else {
$msg = sprintf("\tChild exited with value %d -- ", $? >> 8);
warn $msg;
}

The actual exit code $? >> 8 is supplied by whatever ran and so its interpretation is up to that application. You need to look through its docs and hopefully its exit codes are documented.


Note that $ssh->error seems designed for this task. From the module's docs

my $output = $ssh->capture({ timeout => 10 }, "echo hello; sleep 20; echo bye");
$ssh->error and warn "operation didn't complete successfully: ". $ssh->error;

The printed error needs further investigation. Docs don't say what it is, but I'd expect the unpacked code discussed above (the question update indicates this). Here $ssh only runs a command and it doesn't know what went wrong. It merely gets back the command's exit code, to be looked at.

Or, you can modify the command to get the STDERR on the STDOUT, see below.


The capture method is an equivalent of Perl's backticks (qx). There is a lot on SO on how to get STDERR from backticks, and Perl's very own FAQ has that nicely written up in perlfaq8. A complication here is that this isn't qx but a module's method and, more importantly, it runs on another machine. However, the "output redirection" method should still work without modifications. The command (run by $ssh) can be written so that its STDERR is redirected to its STDOUT.

$cmd_all_output = 'your_whole_command 2>&1';
$ssh->capture($cmd_all_output);

Now you will get the error that you see at the terminal ("no such file or directory") printed on STDOUT and so it will wind up in your $stdout. Note that one must use sh shell syntax, as above. There is a big bit more to it so please look it up (but this should work as it stands). Most of the time it is the same message as in the exit code description.

The check that you have in your code is good, the first line of defense: One should always check $? when running external commands, and for this the command to run need not be touched.

Capturing ssh output in bash script while backgrounding connection

A process going to the background gets its own copies of the file descriptors. The stdout (o=..) will not be available in the calling process. However, you can bind the stdout to a file and access the file.

ssh $s "$@" >outfile &
wait
o=$(cat outfile)

If you don't like files, you could also use named pipes. This way the 'wait' is done by the 'cat' command. The pipe can be reused and consumes no space on the disk.

mkfifo testpipe
ssh $s "$@" >testpipe &
o=$(cat testpipe)

SSH Remote command exit code always get 0

I should use single quotation marks to double quotation marks.
echo $? will become "0", if I use double quotation marks to execution ssh command.

ssh 127.0.0.1 'ssh_test/test.sh; echo $?'



Related Topics



Leave a reply



Submit