我无法弄清楚这有什么问题。 当我在terminal中运行它并input密码时,什么都不会发生,但是如果我在terminal中单独运行每个命令,它都会起作用。 谢谢!
#!/bin/bash sudo su; mkdir /opt/D3GO/; cp `pwd`/D3GO /opt/D3GO/; cp `pwd`/D3GO.png /opt/D3GO/; cp `pwd`/D3GO.desktop /usr/share/applications/; chmod +x /opt/D3GO/D3GO
命令sudo su
启动一个交互式的根shell,但是它不会将当前的shell转换为一个根shell。
做你想做的事情的成语是这样的(感谢@CharlesDuffy的额外的谨慎):
#check for root UID=$(id -u) if [ x$UID != x0 ] then #Beware of how you compose the command printf -v cmd_str '%q ' "$0" "$@" exec sudo su -c "$cmd_str" fi #I am root mkdir /opt/D3GO/ #and the rest of your commands
这个想法是检查当前用户是否是root,如果不是,用su
重新运行相同的命令
sudo su
不是在shell中运行的命令 – 它启动一个新的shell 。
新的shell不再运行你的脚本,运行这个脚本的旧shell等待新脚本退出,然后继续运行。
您可以使用“这些文档”将输入重定向到交互式shell脚本。 运算符<<
是读取输入的指令,直到找到包含指定分隔符的行为EOF
(文件结尾)为止。
sudo su <<EOF echo "code" EOF
例如
#!/bin/bash sudo su <<EOF mkdir /opt/D3GO/ cp `pwd`/D3GO /opt/D3GO/ cp `pwd`/D3GO.png /opt/D3GO/ cp `pwd`/D3GO.desktop /usr/share/applications/ chmod +x /opt/D3GO/D3GO EOF
被接受的答案效果很好,但是可以简化 使用sudo
按需求重新调用脚本的习惯用法,并使其更加便携 :
[[ $(id -u) -eq 0 ]] || exec sudo /bin/bash -c "$(printf '%q ' "$BASH_SOURCE" "$@")"
使用[[ ... ]]
而不是使操作数前缀x
(或双引号LHS)是不必要的。
使用bash -c
而不是su -c
来解释重建的命令行使命令更加便携,因为不是所有的平台都支持su -c
(例如,macOS不支持)。
在bash
, $BASH_SOURCE
通常是引用正在运行的脚本的更可靠的方式。
通过上述方法,参数中的任何变量引用或命令/算术替换总是被调用 shell扩展。
如果你想要延迟扩展 – 这样变量引用不会被扩展,直到sudo
shell运行,在root用户的上下文中使用:
(( __reinvoked )) || exec sudo -s __reinvoked=1 "$BASH_SOURCE" "$@"
请注意,您将不得不单独引用任何包含变量引用或命令替换的参数,以使其延迟展开; 例如'$USER'
。
请注意使用ad-hoc环境变量__reinvoked
来确保只重新调用一次 (即使最初已经以root用户身份进行调用)。
下面是一个演示第一种技术的示例脚本 :
如果不以root身份调用,脚本将使用sudo -s
重新调用自身,按原样传递所有参数。
除非先前已经过认证,并且在超时期限内, sudo
会提示输入管理员密码。
#!/bin/bash [[ $(id -u) -eq 0 ]] || exec sudo /bin/bash -c "$(printf '%q ' "$BASH_SOURCE" "$@")" # Print the username and all arguments. echo "Running as: $(id -un)" echo "Arguments:" for arg; do echo " $((++i)): [$arg]"; done
acfreitas的有用答案演示了一个“script- in -a-script”技术 ,其中一个here-document被用来通过stdin提供shell代码给sudo su
。
再次, sudo -s
就足够了 , 引用是很重要的 :
sudo -s -H <<'EOF' echo "$HOME" EOF
请注意,在这种情况下,如何打开这里的文档分隔符( EOF
,以防止文档的内容由当前 shell 进行前置解释。
如果您没有引用( EOF
任何部分), $HOME
将被展开到当前用户的主目录。
如果你想混合预先和延迟扩展 ,留下这里的开放 – 文档分隔符不加引号,并有选择地\
quoted $
实例:
sudo -s -H <<EOF echo "Called by: $USER; root's home dir: \$HOME" EOF
由于运行“sudo su”会打开一个新的shell,并且该命令在您退出该shell之前不会返回。 也许将脚本分成两个文件:第一个运行sudo并在sudo下执行第二个脚本。
sudo su将尝试以root身份启动一个新的shell。 一旦新的shell被打开,原来的脚本将不会继续,直到新的shell被关闭。
对于一个修复尝试:
在shell脚本中尝试:
su <username> -c "my command"
所以如果用户是“userA”:
su userA -c "mkdir /opt/D3GO/"
但是,如果您是userA,并且想要以root身份运行脚本的一部分,则会提示您输入密码。
su root -c "mkdir /opt/D3GO/"
你也可以通过首先使用sudo运行脚本来解决这个问题
sudo ./myScript.sh
这样,脚本将原始用户保留在脚本中,您可以使用$ {USERNAME} , $ {UID}等标准变量来访问脚本
取决于什么对你更好。