1

GNU bash, version 4.3.27

I'm running into an odd issue with a script that writes output to a file. The script ssh's to a list of servers and records the state/substate of a few services. I then store the results in an array.

If I type into the console window while its running however, the input gets stored into the array $result_arr and I don't know why

#!/bin/bash

check_services() { server_number="$1" local result local result_arr local error_flag="OK"

#Get service status result=$(ssh server.$host -t "$cmds_services")

#trim carriage returns if present result=$(echo "$result" | tr -d '\r')

#split result into array by line readarray -t result_arr <<<"$result"

echo "$server_number,${result_arr[0]},${result_arr[1]},${result_arr[2]},${result_arr[3]},${result_arr[4]},${result_arr[5]},${result_arr[6]},${result_arr[7]}" >> "$OUTFILE" }

main() { for server in $(cat /home/data/serverlist) do clear -x echo "Gathering Data...Server $server" check_services "$server" done

}

When I spam 'a' and enter while the script runs, $OUTFILE will look something like this:

1234,active,mounted,active,mounted,a,,a,a 

instead of

1234,active,mounted,active,mounted,active,mounted,active,mounted
muru
  • 72,889
Juts
  • 13
  • What do you mean by, "When I spam 'a' and enter while the script runs"? To me, spam is stuff that's unwanted – Chris Davies Oct 16 '23 at 19:57
  • @KamilMaciorowski I do not need it, sorry was leftover from some previous work. I've removed it and that seems to have fixed it. I'm going to test some more. Im possibly more confused now! – Juts Oct 16 '23 at 20:05
  • 1
    as an aside, you could use readarray -t result_arr < <( ssh ... | tr -d '\r') to do without the intermediate mangling by echo and the command substitution (the latter would remove trailing empty lines). Those CRs you get are also possibly due to ssh -t, try e.g. ssh -t localhost echo foo |od -c and the same without -t. – ilkkachu Oct 16 '23 at 20:32

1 Answers1

3

This happens because you used ssh -t. The -t option allocates a tty on the remote side.

When the remote command works, the remote tty is most likely in a mode where it echoes the input. It's like when you locally run cat and type to it, you see the input echoed by the tty (not by cat) and only upon Enter or Ctrl+d cat reads it and prints as its output.

In your case the remote tty echoes what your local ssh reads from its stdin. This is then captured by result=$(ssh …) along with the "real" output of the remote commands.

If you don't need a remote tty, do not pass -t to ssh.

If you do need a remote tty, pass -t but don't let ssh read from the local stdin: </dev/null ssh -t …. Note you won't be able to type to the remote command at all.

If you do need a remote tty and you do need to pass (type) something from the local stdin to the remote command, pass -t, do not redirect stdin to /dev/null, but tell the remote tty to turn off its echo. You do this by adding stty -echo; to the beginning of your $cmds_services. You don't need to turn echo on (with stty echo) at the end because the remote tty will be destroyed anyway. Note any of the commands in $cmds_services may reconfigure the tty; depending on the command, you may or may not be able to prevent this.

In a really demanding case you may find this question of mine useful: ssh with separate stdin, stdout, stderr AND tty. Even if you don't need it, you can get some insight from it, from my answer there and from links therein.

  • Brilliant, thank you for taking the time to write that out. – Juts Oct 16 '23 at 20:25
  • 1
    and ssh -t likely disables the echo on the local terminal which you'd usually get, and which is why it's hard to see the difference when just running ssh vs ssh -t interactively – ilkkachu Oct 16 '23 at 20:26