3

I have a script that reads a file line by line and does stuff based on what it reads. One of the things it does is ssh to a remote server and gets some information. For some reason that's completely beyond me, this stops the reading of lines from the file.

The script is essentially (I've cut out a lot of it to simplify the question, so don't worry if it looks like it doesn't really do anything):

cat $csv | while read line; do
   shopt -s nocasematch
   for j in "${file_list[@]}"; do
      found=0;
      for i in $(ssh some_server "ls /some_path/${line:0:1}/${line:1:1}/$line*"); do
         if [[ $i =~ .*$j$ ]]; then
            echo "do something";
            found=1;
            break;
         fi;
      done;
      if [[ $found -ne 1 ]]; then
         echo "don't have $j";
      fi;
      if [[ $found -ne 1 && $j == '\.pdf' ]]; then
         getPDF $line ${dest};
      fi;
   done;
   shopt -u nocasematch
done

This script winds up only running on the first line of the csv. If I replace the "ssh" part of the script with anything else though, it runs all the way through on all lines of the file. What gives?

2
  • 2
    Is ssh eating your stdin (here, your useless use of cat is stdin) ? Try ssh -n and see what happens ... Commented Jul 5, 2011 at 15:30
  • 1
    I strongly recommend you always use read -r when doing line by line reading of a file, and you probably want while IFS=$'\n' read -r at that if whitespace is important to you. Commented Jul 5, 2011 at 16:43

2 Answers 2

10

ssh is consuming stdin. Pass -n.

Sign up to request clarification or add additional context in comments.

1 Comment

That did it. Thanks! For those of you looking at this in the future who want more explanation, look up the -n option by running "man ssh." The final working version of the script is the same as above, except that the ssh part reads "ssh -n some_server..."
1

If you run commands which read from stdin (such as ssh) inside a loop, you need to ensure that either:

  • Your loop isn't iterating over stdin
  • Your command has had its stdin redirected:

The former:

while read -u 5 -r; do
  ssh "$REPLY" ...
done 5<file

...which, using bash 4.1 or newer, can be rewritten with automatic file descriptor assignment as so:

while read -u "$file_fd" -r; do
  ssh "$REPLY" ...
done {file_fd}<file

The latter:

while read -r; do
  ssh "$REPLY" ... </dev/null
done <file

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.