我在本地用户中保存了一个名为 ( executeAdM.sh
) 的 shell 脚本,当我执行此脚本时,我会通过从指令文件中获取命令来切换到 sudo 用户。但是当我执行此脚本时,我还会传递参数,这些参数实际上是 sudo 用户的某个目录路径。请参阅下面的脚本。
本地用户脚本 ( executeADM.sh
):
#!/bin/bash
echo password | sudo -S -l
sudo /usr/bin/su - user <<\EOF
#ls -lrt
pwd
for entry in $(ls -r)
do
if [ "$entry" = "testingADM.sh" ];then
./"$entry" "$1"
fi
done
EOF
我正在执行上述操作:
./executeADM.sh "/global/u70/globe/ADM"
当上述脚本执行时,它会成功切换到其他用户,并且使用 sudo 用户我执行一个for
循环,搜索另一个名为 的脚本testingADM.sh
。
一旦找到脚本,我就会使用从本地用户传递的参数执行该脚本,并且testingADM.sh
应该为我设置路径。
这不起作用——它没有读取从本地用户传递的参数。
sudo 用户脚本(testingADM.sh
):
#!/bin/bash
changepath=$1
cd "$changepath"
pwd
当我在脚本中对路径变量进行硬编码时,一切都正常。但我不想这样:
#!/bin/bash
changepath=somepath
cd "$changepath"
pwd
问题是,它不是转到 而是"/global/u70/globe/ADM"
将路径作为"/global/u70/globe/"
,这是我执行 之后的路径sudo
。它只是没有传递变量。
根据以下建议,我最终得到了以下结果:
#!/bin/bash
echo password | sudo -S -l
sudo /usr/bin/su - user <<EOF
#ls -lrt
#pwd
echo "$1"
./testingADM.sh "$1"
EOF
该echo
命令不打印任何内容;显示空白。当我更改\EOF
为时,它起作用了EOF
。
有人能解释一下以下之间的区别吗:
\EOF , "EOF" , 'EOF' , EOF
或者说前三个意思是一样的吗?那他们之间有什么区别呢?
答案1
不要引用或转义你的 heredoc 限制字符串(即使用EOF
或\EOF
)"EOF"
,否则,像 这样的特殊变量$
将不会被解释。请参阅这里了解更多信息和示例(例如示例 19-7)。
这是一个可以运行的最小脚本:
$ cat test.sh
#!/bin/bash
sudo su - $(whoami) <<EOF
./test2.sh "$1"
EOF
$ cat test2.sh
#!/bin/bash
foo=$1
echo "$foo"
$ ./test1.sh "/path/to/file"
"/path/to/file"
注意:
- 根本不需要 heredoc。只需
./test2.sh
在之后直接调用即可sudo
:sudo -u $(whoami) test2.sh "$1"
- 您不应该循环输出
ls
。 - 无需循环
for
搜索单个文件。只需直接使用其名称调用脚本即可。
您还应该引用您的变量,即:
- 使用以下命令执行脚本
./executeADM.sh "/path/with white/space"
- 调用
./"$entry" "$1"
你的脚本 - 在您的其他脚本中,使用
cd "$path"
一般来说:
- 始终使用双引号括住变量。(不要使用单引号括住它们 - 它们不会扩展。)
- 不要使用名为 的变量
path
。(就像您不会使用名为 、 等的变量一样user
。home
)
答案2
编辑
从我的脑海里。你的路径包含空格吗?
如果是,则需要按如下方式执行./executeADM.sh 'somePath'
。
$1
在进一步传递时,最好将其保存到变量中,这样更容易阅读。我会path=$1
在批处理文件中添加,您将./$entry "$path"