2

I have a simple script with while loop, but cannot understand, why it breaks after first line, from $vault_list variable:

#!/bin/bash

tech_login="$1"
vault_list=$(docker exec -i tmgnt_vault_1 vault list secret/${tech_login}-terminals | sed 1,2d)

while IFS= read -r terminal
do
    echo "line is $terminal"
    key_values=$(docker exec -i tmgnt_vault_1 vault read secret/${tech_login}-terminals/$terminal )


done <<< "$vault_list"

If I remove $key_values from while loop, it returns all values in echo "line is $terminal". Can anyone point me, what is the problem with while loop? I assume, that this can be a problem with output, but not sure.

6
  • Does docker exec -i tmgnt_vault_1 vault read secret/${tech_login}-terminals/$terminal work if you run it separately? Commented Oct 11, 2018 at 11:03
  • yes, it returns values if I start it separately Commented Oct 11, 2018 at 11:05
  • 4
    Docker or the command you run inside it eats the rest of stdin, so there's nothing left to read in the next iteration. Commented Oct 11, 2018 at 11:13
  • Yes, that helps! Commented Oct 11, 2018 at 11:24
  • ugh :-P how do we stop it eating the rest of stdin ? Commented Nov 13, 2019 at 16:42

3 Answers 3

4

Hopefully this will help others.
ssh might be the command that is eating stdin.
It was for me.

e.g. ssh inside a while loop was causing the loop to exit after first iteration.

LIST="cid1 10.10.0.1 host1
cid2 10.10.0.2 host1
cid3 10.10.0.3 host2"

# this while loop exits after first iteration
# ssh has eaten rest of stdin
echo "$LIST" |while read -r cid cip chost; do
    echo $cid;
    PSINFO=$(ssh $chost docker exec -i $cid "ps -e -orss=,pid=,args=,cmd=" |grep java );
    echo PSINFO=$PSINFO; 
done; 

SOLVED by directing ssh to take stdin from /dev/null using </dev/null:

# this while loop keeps on running
# ssh directed to take stdin from /dev/null
echo "$LIST" |while read -r cid cip chost; do
    echo $cid;
    PSINFO=$(ssh $chost docker exec -i $cid "ps -e -orss=,pid=,args=,cmd=" </dev/null |grep java );
    echo PSINFO=$PSINFO; 
done; 
Sign up to request clarification or add additional context in comments.

2 Comments

Yes. for sure, ssh consumes the stdin. You can use the -n flag to as in "ssh -n" instead of < /dev/null. The code will look nicer and more readable. Check man.openbsd.org/ssh.1 and look for -n.
InteReStinG. Thank you. That looks like a proper solution rather than a hack redirecting /dev/null. Good to read up on ssh -n and -f flags.
2

With hint from @choroba I found right syntax for $key_values:

key_values=$(docker exec -i tmgnt_vault_1 vault read secret/${tech_login}-terminals/$terminal <<<$terminal)

I was need to pass the $terminal variable explicitly to the docker command, which can be done with a here-string, "<<

Comments

1

Had the same issue with aws ecs execute-command. While the loop was interrupted right after the first execution. Unfortunately, it does not have -n flag, but a trick with < /dev/null helped.

So, the correct way to run a command for each task in the cluster is:

$ aws ecs list-tasks --cluster prod-cluster --service prod-service --region prod-region \
    | grep arn:aws:ecs:prod-region \
    | sed 's_.*/__g;s/[",]//g' \
    | while read task; do 
        echo $task; 
        aws ecs execute-command --cluster prod-cluster --task ${task} --container prod-image --command "uptime" --interactive < /dev/null \
            | grep 'load average'; 
    done

It will show uptime for all tasks running currently in the cluster

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.