【发布时间】:2016-12-20 21:04:15
【问题描述】:
我有一个在服务器之间复制文件的脚本。我正在使用 lsof 命令来确保文件在移动之前没有被写入。运行脚本的用户和写入文件的用户不同,所以我需要对文件所有者进行 sudo。这是 sudoers 文件中的相关行:
userA ALL=(userB:userB) NOPASSWD: ALL
在主脚本(以 userA 身份运行)中,我尝试调用 sudo,然后调用包含 lsof 命令的下标:
sudo su - userB -c 'source ./getOpenFiles.sh'
getOpenFiles.sh 有这一行:
#!/bin/bash
lsofResult=$(/usr/sbin/lsof "${sourcePath}")
我也试过调用下标:
source ./getOpenFiles.sh
那么下标的第一行就是sudo:
#!/bin/bash
sudo su - banjobs
lsofResult=$(/usr/sbin/lsof "${sourcePath}")`.
这两种解决方案都不起作用。
【问题讨论】:
-
当你运行
sudo su - banjobs时,下一个命令直到你的sudo su完成并退出后才会运行,并且没有任何东西以banjobs运行。 -
也就是说它不会将
lsofResult评估为banjobs。 -
...如果你使用
su -c 'source somescript',那么somescript由sh运行,而不是bash,不管它的shebang 说什么。如果您的sh不支持source,那么它根本不会运行。 (编写source的POSIX 兼容方式是. somescript,而不是source somescript)。 -
...也就是说:这里有很多错误,并不是所有的都与
source有关。 (尽管如果您希望source导致在父 shell 中设置变量 - 即运行您的sudo命令的 shell,那将永远无法工作,因为sudo本身就是一个子进程 - -source的重点是直接在您当前的 shell 进程中做某事;如果您在子进程中做任何事情,那完全违背了这一点)。 -
顺便说一句,打算引入 bash 的代码应该以
.bash扩展名命名,而不是.sh扩展名——这样对读者来说代码更明显不打算与 POSIX sh 兼容,但特别是只有在带有 bash 扩展的解释器中才能安全。 (这对于您在此处提供的特定代码并不重要,除了sourceis POSIX-sh-compatible,但认为它是最佳实践说明)。相比之下,对于旨在执行而非来源的命令,根本不具有任何文件扩展名更为合适。