-1

I'm using aws ssm to perform operation task. when executing command similar to the following (details are replaced), The value of variable i is not set correctly when being used in remote execution

What's wrong with my code?

aws ssm send-command --document-name "AWS-RunShellScript" --instance-ids $instance_id \
    --parameters '{"commands":["count=4; for i in { 1..$count }; do echo $i; ssh $(server_$i) bash -c '"'echo $i && echo $(date +%Y-%m-%d)'"'; done;"],"executionTimeout":["3600"]}' \
    --timeout-seconds 600 --region us-west-2
  • the first echo will return 1, 2, 3, 4
  • however the second echo will return 4, 4, 4, 4

Expect: both should return 1,2,3,4

Gordon Davisson
  • 118,432
  • 16
  • 123
  • 151
rrr
  • 369
  • 4
  • 8
  • 1
    See: [Difference between single and double quotes in bash](http://stackoverflow.com/q/6697753/3776858) – Cyrus Dec 29 '18 at 07:20
  • 1
    I've edited the question to use code format (the four-space prefix thing), and broke it into three lines w/ continuations rather than one long one; this shouldn't change the meaning. But the result it still pretty hard to make sense of. It looks to me like you at least have quoting problems: you appear to be trying to nest single-quoted strings inside another single-quoted string, and that does not work at all. BTW, `{ 1..$count }` is also not valid shell syntax, since braces get expanded before variables are replaced. – Gordon Davisson Dec 29 '18 at 07:25
  • The quoting in the Bash command line is clearly broken, but I can't figure out what the code is really meant to do. Can you explain what it should do, or perhaps [edit] the question to show a working script which does what you want locally? – tripleee Dec 29 '18 at 07:53

1 Answers1

1
ws ssm send-command --document-name "AWS-RunShellScript" --instance-ids $instance_id \
    --parameters '{"commands":["count=4; for i in { 1..$count }; do echo $i; ssh $(server_$i) bash -c '"'echo $i && echo $(date +%Y-%m-%d)'"'; done;"],"executionTimeout":["3600"]}' \
    --timeout-seconds 600 --region us-west-2

Let's break down your commands, step by step. First, it contains a long string parameter:

--parameters '{"commands":["count=4; for i in { 1..$count }; do echo $i; ssh $(server_$i) bash -c '"'echo $i && echo $(date +%Y-%m-%d)'"'; done;"],"executionTimeout":["3600"]}' here in command line, it is felt like this:

Part1 :'{"commands":["count=4; for i in { 1..$count }; do echo $i; ssh $(server_$i) bash -c '

Part2: "'echo $i && echo $(date +%Y-%m-%d)'"

Part3: '; done;"],"executionTimeout":["3600"]}'

Now can you see why it is always 4.

In part2, the $i is expanded directly. After you executed the loop, here your $i is not local, and after your execution (may not successfully at first time),you $i=4 in your shell now.

whitebob
  • 48
  • 6
  • The fix is quite easy. In part 2, you want literal `"`, so do not use `'` to quote it, because you are in a single quote environment. Use backslash instead will make it work. `ws ssm send-command --document-name "AWS-RunShellScript" --instance-ids $instance_id \ --parameters '{"commands":["count=4; for i in { 1..$count }; do echo $i; ssh $(server_$i) bash -c \"echo $i && echo $(date +%Y-%m-%d)\"; done;"],"executionTimeout":["3600"]}' \ --timeout-seconds 600 --region us-west-2` – whitebob Dec 29 '18 at 07:59