如何在heredoc中处理shell脚本参数?

时间:2015-09-01 18:55:19

标签: shell

我需要切换到oracle用户才能更改tnsnames.ora文件的权限。我将此文件路径作为参数传递,但看起来在某处语法错误。感谢帮助解决这个问题。

Belows是我剧本的基础。

#!/bin/bash

sudo su - oracle <<-"EOF"
    chmod 777 "$1"
EOF

由于出现以下错误而失败:

/home/itsh->./dothis.sh /home/oracle/orasys/11.2.0.2/network/admin/tnsnames.ora
chmod: cannot access `': No such file or directory

2 个答案:

答案 0 :(得分:1)

此处文档的操作指定为in the POSIX spec,其中显示:

  

如果引用了单词中的任何字符,则应通过对单词执行引用删除来形成分隔符,并且不应扩展此处 - 文档行。否则,分隔符应为单词本身。

     

如果引用单词中没有字符,则应扩展here-document的所有行以进行参数扩展,命令替换和算术扩展。在这种情况下,输入中的行为与内部双引号相同(请参阅双引号)。但是,双引号字符('“')不应在here-document中特别处理,除非双引号出现在”$()“,”``“或”$ {}“中。 / p>

因此,使用<<-"EOF"(而不是<<-EOF)作为此处的文档标记,您明确告诉shell 扩展任何变量(来自shell上下文)这里的文档内容。

当您使用heredoc作为shell片段时,这通常是您想要的,但在您的情况下,这与您正在寻找的内容完全相反。

答案 1 :(得分:1)

如果你担心安全性,那么正确的做法就是不要改变你的引用,而是保持原样,并使用bash -s将你的参数传递给运行的shell作为oracle用户直接:

#!/bin/bash
sudo -u oracle bash -s "$@" <<-'EOF'
    chmod 777 "$1"
EOF

...或者,如果你必须使用sudo su - oracle(我认为这是不好的做法,最好避免使用):

#!/bin/bash
printf -v sudo_cmd '%q ' bash -s "$@"
sudo su - oracle -c "$sudo_cmd" <<-'EOF'
    chmod 777 "$1"
EOF

使用这些实践中的任何一种,您的内部shell都会运行$1扩展本身 - 并且命令行上的数据不会替换为代码。< / p>