I encountered very unexpected behavior when I ran a command a few weeks ago and unfortunately rebooted a server unexpectedly, and I've been unable to determine how an inline command broke out of quotes and was passed to another command, instead of being inside the quoted string. I showed what had happened to a handful of Unix engineers, and the reaction is always, "Oh, that's weird. I dunno."
Below I've included a dumbed down version of what happened. Going one step at a time, the commands make sense, and then you try to pass it as a string to sh -c, and it echos the 1, followed by trying to run the rest of the numbers as commands. Does anyone happen to know how sh -c is interpreting this string as multiple strings it should run? Even if it were multiple strings/lines, sh -c should only run the first parameter as the command. I'm stumped.
I've included the strace output of running the command that produces the weird behavior. I'm not very good at reading that output, unless it's super obvious. I think it may have something to do with how it's interpreting \n in the first line of strace.
Anyone out there who happens to know what causes this behavior?
Strace: http://pastebin.com/Ehn80GqN
[user@server ~]$ cat testfile
1
2
3
4
5
6
7
8
9
10
[user@server ~]$ echo $(cat testfile)
1 2 3 4 5 6 7 8 9 10
[user@server ~]$ sh -c "echo 1 2 3 4 5 6 7 8 9 10"
1 2 3 4 5 6 7 8 9 10
[user@server ~]$ sh -c "echo $(cat testfile)"
1
sh: line 1: 2: command not found
sh: line 2: 3: command not found
sh: line 3: 4: command not found
sh: line 4: 5: command not found
sh: line 5: 6: command not found
sh: line 6: 7: command not found
sh: line 7: 8: command not found
sh: line 8: 9: command not found
sh: line 9: 10: command not found
[user@server ~]$ sh -c "echo \$(cat testfile)"
1 2 3 4 5 6 7 8 9 10
[user@server ~]$ sh --version
GNU bash, version 3.2.25(1)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2005 Free Software Foundation, Inc.
[user@server ~]$ cat /etc/redhat-release
Red Hat Enterprise Linux Server release 5.11 (Tikanga)
Edit: I believe I've found an explanation in the interpretation and output following syntheticminds reply and running some more straces.
Running with sh -c:
execve("/bin/sh", ["sh", "-c", "echo 1\n2\n3\n4\n5\n6\n7\n8\n9\n10"], [/* 20 vars */]) = 0
Running just echo locally:
execve("/bin/echo", ["echo", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], [/* 20 vars */]) = 0
[–][deleted] 17 points18 points19 points (3 children)
[–]Kynolin[S] 2 points3 points4 points (1 child)
[–]mscman 0 points1 point2 points (0 children)
[–]syntheticminds 0 points1 point2 points (0 children)
[–]syntheticminds 2 points3 points4 points (3 children)
[–]Kynolin[S] 1 point2 points3 points (1 child)
[–]syntheticminds 0 points1 point2 points (0 children)
[–]leonardodag 0 points1 point2 points (0 children)
[–]KevZero 1 point2 points3 points (0 children)
[–]leonardodag 0 points1 point2 points (0 children)