This code has been failing for days and I'm at my wit's end. Maybe someone can help.

I've coded a bash script that is supposed to loop through managed Linux systems. It calls another bash script to get records with 8 fields:

local cmd="/usr/local/sbin/zlsexpirations -s -l $nodeList"
local expList                            # list of nodes and expiration days
expList=`$cmd`                           # run the command


So the variable 'expList' has the records. It should then loop through all the records passing them to the function zSetOneSystem() to process one system at a time. Here's the main loop (the double quotes around expList are needed to pass a record, not just one token):

local nextLine
while read nextLine; do
  zVerbose "calling zSetOneSystem $nextLine"
  zSetOneSystem $nextLine
done < <(echo "$expList")

This was my first attempt at the loop:

echo "$expList" |
while read nextLine; do
  zVerbose "calling zSetOneSystem $nextLine"
  zSetOneSystem $nextLine

Both flavors of the loop above have this behavior:

  1. If the -n flag (no operation) is passed, the loop runs fine to completion.
  2. If that flag is not passed, the loop runs, processes one system (which results in files being changed on disk), but then the loop simply stops.

When I trace it, the 'read nextLine' fails. I print out 'expList' after the loop and all records are still in place. How can a sub-process affect the parent this way? I've narrowed it down to two resulting bash script calls nested deeper in zSetOneSystem(). If I comment out those two, the loop succeeds. If I un-comment either of the two bash scripts, the loop fails as described. Strange.

Any help will be appreciated.


  • It's pretty clear that 'stdin' was getting 'drained' somewhere down the stack (I'm still now sure where). Using another file descriptor instead of stdin (0) worked around the issue: exec 3<&0 # Link file descriptor #3 with stdin. local nextLine while read -u 3 nextLine; do zVerbose "calling zSetOneSystem $nextLine" zSetOneSystem $nextLine done 3< <(echo "$expList") # read from expList on fd 3 Thanks to @l0b0 – Michael MacIsaac May 4 '17 at 15:17

You are passing the input to the while loop on standard input (file descriptor 0). Any commands inside the loop which read from standard input will consume that stream, making the content not available for read the second time around. This is a common issue with passing standard input to what is effectively multiple commands. The easiest way to fix this is to use a file descriptor that the commands inside the loop are unlikely to use, for example:

while read -u "$fd" line
done {fd}< <(input command(s))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.