我正在尝试向 cron.d 追加/回显命令。但是,当运行回显命令的脚本时:
echo */2 * * * * /usr/bin/aws ssm-send-command --document-name "AWS-RunShellScript" --parameters '{"commands":["echo {{ssm:/mr2/cloudwatch-custom}}"]"}' --instance-ids "$INSTANCE_ID" --region us-east-1 >> /etc/cron.d/lvm_disk_space
我找出它写入的文件,其中包含以下内容:
*/2 boot-finished cloud-config.txt datasource handlers obj.pkl scripts sem user-data.txt user-data.txt.i vendor-data.txt vendor-data.txt.i boot-finished cloud-config.txt datasource handlers obj.pkl scripts sem user-data.txt user-data.txt.i vendor-data.txt vendor-data.txt.i boot-finished cloud-config.txt datasource handlers obj.pkl scripts sem user-data.txt user-data.txt.i vendor-data.txt vendor-data.txt.i boot-finished cloud-config.txt datasource handlers obj.pkl scripts sem user-data.txt user-data.txt.i vendor-data.txt vendor-data.txt.i /usr/bin/aws ssm-send-command --document-name AWS-RunShellScript --parameters {"commands":["echo {{ssm:/mr2/cloudwatch-custom}}"]"} --instance-ids --region us-east-1
我假设*
事情搞砸了。当我尝试用引号括起来时,我总是得到:
echo "*/2 * * * * /usr/bin/aws ssm-send-command --document-name "AWS-RunShellScript" --parameters '{"commands":["echo {{ssm:/mr2/cloudwatch-custom}}"]"}' --instance-ids "$INSTANCE_ID" --region us-east-1" >> /etc/cron.d/lvm_disk_space
./user-data.txt: line 30: unexpected EOF while looking for matching `"'
./user-data.txt: line 31: syntax error: unexpected end of file
有没有安全的方法来逃避引号?
答案1
第一个命令的问题是*
字符未加引号。因此,shell 会将它们扩展为当前目录中任何匹配的文件名。
第二个命令的问题是该命令同时包含单引号和双引号,因此您无法像您尝试的那样可靠地用双引号引用 crontab 条目。您必须重写它,以便它首先只包含单一类型的引号(例如双引号),然后使用其他类型的引号(单引号)来引用完整的命令。 crontab 条目还包含一个拼写错误(我不会尝试纠正它,因为我不知道它是什么应该be) 因为它有奇数个双引号。
更好的方法是使用引用的此处文档:
cat >>/etc/cron.d/lvm_disk_space <<'END_CRON'
*/2 * * * * /usr/bin/aws ssm-send-command --document-name "AWS-RunShellScript" --parameters '{"commands":["echo {{ssm:/mr2/cloudwatch-custom}}"]"}' --instance-ids "$INSTANCE_ID" --region us-east-1
END_CRON
这使用引用的此处文档重定向将文字文本写入文件末尾。由于初始标签周围有引号,shell 不会“戳”(扩展或以其他方式修改)此处文档的内容END_CRON
。
请注意,您的命令仍然包含一个开放双引号,您必须自行修复:
["echo {{ssm:/mr2/cloudwatch-custom}}"]"
答案2
正确引用的行应该如下所示:
$ echo \*/2\ \*\ \*\ \*\ \*\ /usr/bin/aws\ ssm-send-command\ --document-name\ \"AWS-RunShellScript\"\ --parameters\ \'\{\"commands\":\[\"echo\ \{\{ssm:/mr2/cloudwatch-custom\}\}\"\]\"\}\'\ --instance-ids\ \"\$INSTANCE_ID\"\ --region\ us-east-1
当然,我自己并没有想出这个疯狂的引用,我使用了这个使用%q
说明符的脚本:
#!/usr/bin/env sh
read
printf "%q\n" "$REPLY" | tr '\n' ' '
答案3
尝试分成两个字符串
echo "*/2 * * * *" /usr/bin/aws ssm-send-command (...) >> /etc/cron.d/lvm_disk_space
这种方式*
不会扩展到本地文件名,并且您会得到剩余的参数。
请注意,外部引用已被删除。
例如
--document-name "AWS-RunShellScript"
被展开为
--document-name AWS-RunShellScript