如何在 bash 脚本开始时请求提升权限并在结束时释放它?

发布于 2025-01-17 03:52:45 字数 698 浏览 4 评论 0原文

我有一个脚本(myscript.sh),它运行一些需要提升权限的命令(即需要使用sudo运行)。

脚本非常复杂,但演示如下:

#!/bin/bash
echo "hello"
command1_which_needs_sudo
echo "hello2"
command2_which_needs_sudo
echo "hello3"
...

如果我以普通用户身份运行它,而没有所需的权限:

$ ./myscript.sh
hello
must be super-user to perform this action

但是,如果我使用正确的权限运行它,它将正常工作:

$ sudo ./myscript.sh
hello
hello2
hello3

我可以以某种方式实现运行 myscript.sh 不带 sudo,并使脚本在开始时仅请求一次(并在完成后将其传回)?

显然, sudo command1_which_needs_sudo 不会很好,因为 command2 也需要特权。

如果我不想创建另一个文件,并且由于脚本复杂性,我也不想使用heredoc语法来执行此操作,我该如何执行此操作?

I have a script (myscript.sh) which runs a few commands which need elevated privileges (i.e. needs to run with sudo).

Script is quite complex, but to demonstrate it is like below:

#!/bin/bash
echo "hello"
command1_which_needs_sudo
echo "hello2"
command2_which_needs_sudo
echo "hello3"
...

If I run it as a normal user without the required privileges:

$ ./myscript.sh
hello
must be super-user to perform this action

However if I run it with the correct privileges, it will work fine:

$ sudo ./myscript.sh
hello
hello2
hello3

Can I somehow achieve to run myscript.sh without sudo, and make the script requesting the elevated privileges only once in the beginning (and pass it back once it has finished)?

So obviously, sudo command1_which_needs_sudo will not be good, as command2 also need privileges.

How can I do this if I don't want to create another file, and due to script complexity I also don't want to do this with heredoc syntax?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

美男兮 2025-01-24 03:52:45

如果您想以 root 权限运行脚本,而不必在终端中键入 sudo 也不必多次键入密码,则可以使用:

#!/bin/bash

[[ "$EUID" == 0 ]] || exec sudo -s "$0" "$@"

echo "hello"
command1_which_needs_sudo
echo "hello2"
command2_which_needs_sudo
echo "hello3"
# ...

sudo -k
  • EUID是一个 bash 变量,用于存储当前使用的用户 ID。如果不是 0(又名 root),那么您需要提升权限,这是通过 exec sudo ... 完成的。< /p>

  • 脚本末尾的

    sudo -k 撤销缓存的 sudo 权限

  • 警告:使用 $0调用脚本本身并不是100%可靠;为了安全起见,您应该使用脚本的完整路径,例如。 exec sudo -s /usr/local/bin/myscript "$@"


如果目标是使用 sudo 权限执行脚本的一部分,则使用 此处引用的文档可能是最简单的解决方案;不会有任何语法问题,因为 shell 不会扩展其中的任何内容。

#!/bin/bash

echo "hello"

sudo -s var="hello2" <<'END_OF_SUDO'

    # NOTE: the indentation is not required
    command1_which_needs_sudo
    echo "$var"
    command2_which_needs_sudo

END_OF_SUDO

sudo -k

echo "hello3"
#...

备注:您可以通过在 sudo 命令中设置 varname=value 来在此处文档脚本中使用外部值。

If you want to run the script with root privileges without having to type sudo in the terminal nor having to type the password more than once then you can use:

#!/bin/bash

[[ "$EUID" == 0 ]] || exec sudo -s "$0" "$@"

echo "hello"
command1_which_needs_sudo
echo "hello2"
command2_which_needs_sudo
echo "hello3"
# ...

sudo -k
  • EUID is a bash variable that stores the user ID currently in use. If it isn't 0 (aka root) then you need to elevate the rights, which is done with exec sudo ....

  • sudo -k at the end of the script revokes the cached sudo rights

  • WARNING: using $0 to call the script itself isn't 100% reliable; to be on safe side you should use the full path to the script instead, for eg. exec sudo -s /usr/local/bin/myscript "$@"


If the goal is to execute a part of the script with sudo rights then using a quoted here‑document is probably the simplest solution; there won't be any syntax issues because the shell doesn't expand anything inside of it.

#!/bin/bash

echo "hello"

sudo -s var="hello2" <<'END_OF_SUDO'

    # NOTE: the indentation is not required
    command1_which_needs_sudo
    echo "$var"
    command2_which_needs_sudo

END_OF_SUDO

sudo -k

echo "hello3"
#...

remark: you can use external values in the here-document script by setting varname=value in the sudo command.

不知所踪 2025-01-24 03:52:45

如果您主要关心的是代码清晰度,那么使用包装函数可以带来很多好处。

# call any named bash function under sudo with arbitrary arguments
run_escalated_function() {
  local function_name args_q
  function_name=$1; shift || return
  printf -v args_q '%q ' "$@"
  sudo bash -c "$(declare -f "$function_name"); $function_name $args_q"
}

privileged_bits() {
  command1_which_needs_sudo
  echo "hello2"
  command2_which_needs_sudo
}

echo "hello"
run_escalated_function privileged_bits
echo "hello3"

If your main concern is code clarity, using wrapper functions can do a lot of good.

# call any named bash function under sudo with arbitrary arguments
run_escalated_function() {
  local function_name args_q
  function_name=$1; shift || return
  printf -v args_q '%q ' "$@"
  sudo bash -c "$(declare -f "$function_name"); $function_name $args_q"
}

privileged_bits() {
  command1_which_needs_sudo
  echo "hello2"
  command2_which_needs_sudo
}

echo "hello"
run_escalated_function privileged_bits
echo "hello3"
自由如风 2025-01-24 03:52:45

其他 5 种方法总是被讨论,但除非不能,否则应该使用最直接的方法:

typeset SUDO="/path/to/sudo"

$SUDO command_w
command_x
$SUDO command_y
command_z

另一个例子,在外部使用密码,

在终端中发出命令,而不是在脚本中设置它:

export PASSWORD="your_password_here"

然后运行 ​​./script.sh 并使用 sudo 命令的密码:

typeset SUDO="/path/to/sudo"

echo "$PASSWORD" | $SUDO command_w
command_x
echo "$PASSWORD" | $SUDO command_y
command_z

最后,您需要取消设置或将密码更改为以下内容:

unset PASSWORD

更新:或者如我所指出的(已经是新的),如果您真的关心 Shell,只需在脚本中查询密码持有该命令的历史带密码。

例如,将其添加到脚本中:

read -rsp 'Enter your password: ' PASSWORD; echo

密码将保存到 $PASSWORD 并且不会在屏幕上显示密码等。“echo”只是为了使脚本输出在其上自己的线。

The other 5 methods were always discussed but the most straightforward should be used unless one can't:

typeset SUDO="/path/to/sudo"

$SUDO command_w
command_x
$SUDO command_y
command_z

Another example, using a password externally,

Issue the command in the terminal opposed to setting it in the script:

export PASSWORD="your_password_here"

Then run ./script.sh and use the password for the sudo commands:

typeset SUDO="/path/to/sudo"

echo "$PASSWORD" | $SUDO command_w
command_x
echo "$PASSWORD" | $SUDO command_y
command_z

Finally you would need to unset or change the password to something:

unset PASSWORD

UPDATE: or as pointed out to me (already new this) that just query for the password in the script if you are really concerned about Shell history holding that command w/password.

For example add this to the script:

read -rsp 'Enter your password: ' PASSWORD; echo

Password will be saved to $PASSWORD and it will not display the password to the screen etc.. The 'echo' is there just to make the script output be on its own line.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文