Let's say I want to do some test VIA ssh
ssh 184.108.40.206 2>/dev/null "smartctl -a /dev/sdb -q silent" echo $? 1
in that case we get exit code 1
How to know if the problem is about ssh or about the smartctl command ?
The determination is difficult as many processes all use the same value.
% ssh 2>/dev/null localhost 'exit 255' ; echo $? 255 % ssh 2>/dev/null nopelocalhost 'exit 0' ; echo $? 255
With a heuristic you could guess which code is from which program based on commonly used exit codes; this would be mostly right, unless the programs involved overlap or something unexpected happens. Standard error may or may not be available and the exit code may change depending on how the program exits:
% ssh localhost ./segfault ; echo $? 255 % ./segfault ; echo $? zsh: bus error ./segfault 138 %
Thus it is not so reliable to guess at where
$? came from. Instead, a better option may be to design a protocol that communicates more information than provided by the exit status word; examples would include Nagios or Ansible that communicate more than just
$? when determining how a remote command ran. This could be as simple as a line of text that depends on how
smartctl ran (or segfaulted, or ...) or something more complicated like a JSON structure with the standard out, err, exit status word, and other such metadata. So instead of running
smartctl directly, you would instead call the wrapper program that runs
smartctl and parses its output, and on the other side of
ssh you would collect that output; if the output is not available, then something went wrong with the
ssh, or with your wrapper program.
EXIT STATUS ssh exits with the exit status of the remote command or with 255 if an error occurred.
If an error occured with ssh command it will return 255, otherwise it returns exit status of remote command.
$ ssh email@example.com ssh: Could not resolve hostname not.exists: Name or service not known $ echo $? 255
In your case 1 is exit status of
smartctl command, not
smartctl exit statuses:
EXIT STATUS The exit statuses of smartctl are defined by a bitmask. If all is well with the disk, the exit status (return value) of smartctl is 0 (all bits turned off). If a problem occurs, or an error, potential error, or fault is detected, then a non-zero status is returned. In this case, the eight different bits in the exit status have the following meanings for ATA disks; some of these values may also be returned for SCSI disks. Bit 0: Command line did not parse. Bit 1: Device open failed, device did not return an IDENTIFY DEVICE structure, or device is in a low-power mode (see '-n' option above). Bit 2: Some SMART or other ATA command to the disk failed, or there was a checksum error in a SMART data structure (see '-b' option above). Bit 3: SMART status check returned "DISK FAILING". Bit 4: We found prefail Attributes <= threshold. Bit 5: SMART status check returned "DISK OK" but we found that some (usage or prefail) Attributes have been <= threshold at some time in the past. Bit 6: The device error log contains records of errors. Bit 7: The device self-test log contains records of errors. [ATA only] Failed self-tests outdated by a newer successful extended self-test are ignored.
exit status 1 on smartctl would mean bit 0 is on, since 1=2^0, so that command line didn't parse