是否可以让 sudo 提示符也显示该命令?
如果您是调用者,那么简单[SUDO] password
就很好了。但您经常运行脚本并想仔细检查您同意的内容。我已经将超时设置为零,因此每次都必须确认。
我很想有类似的东西
[SUDO] PWD: /home/user/
[SUDO] CMD: /bin/ls -la *.c
[SUDO] password: _
答案1
关于*.c
首先,制作sudo
(或任何支持装置)打印会相当棘手/bin/ls -la *.c
,因为当你运行
sudo /bin/ls -la *.c
在 shell 中,它是*.c
在启动之前展开的 shell sudo
。sudo
获取结果扩张,并且没有办法知道它*.c
曾经存在过。
我想魔法别名并且 shell 历史可以做一些事情,但是:
- 您的关注点
sudo
在于脚本。脚本的解释器可能是一个不支持历史记录的 shell;即使它支持,在解释脚本时也可能不会这样做;即使它支持,也可能不会默认使用别名。 - 如果我是你,我会想看到实际的命令到达
sudo
,例如/bin/ls -la bar.c baz.c foo.c
。一个更好的例子是想象脚本调用sudo "$tool" "$arg1" "$arg2"
;你想看到这个吗?或者扩展的实际的命令?
现在我假设你不一定需要看到*.c
,你接受看到任何*.c
扩展到的东西。
包装器
您可以构建一个自定义程序sudo
来打印您想要的内容并调用真实的sudo
。一个相对简单的包装器脚本:
#!/bin/bash
printf '[SUDO] PWD: %s\n' "$PWD" >/dev/tty
printf '[SUDO] CMD: ' >/dev/tty
printf '%s ' sudo "${@@Q}" >/dev/tty
printf '\n' >/dev/tty
exec /usr/bin/sudo "$@"
如果您将脚本命名为sudo
,使其可执行,并将其放置在您的$PATH
before目录中/usr/bin
(注意,我假设您的实际sudo
是/usr/bin/sudo
,包装器也是如此),那么每当您调用 时sudo
,您都会调用包装器。它将(无条件地)在执行实际 之前打印您想要的信息sudo
。
笔记:
为单个用户设置这个很容易,即不影响其他用户:将包装器放在私有
bin
目录中,$PATH
并进行相应修改。可以为所有 sudoers 设置这个(但我不会详细说明)。包装器打印到
/dev/tty
。这是个好主意(想象一下sudo foo >result 2>log
,你不想把result
或弄乱log
)。你的 realsudo
也很可能将其提示打印到 tty。包装器打印的内容类似于
[SUDO] CMD: sudo ls …
而不是[SUDO] CMD: ls …
您想要的。这是设计使然。想象一下命令是sudo -E ls …
,[SUDO] CMD: -E ls …
看起来很奇怪。解析参数只是为了-E
在输出中省略是徒劳的;甚至有害的,你不想知道-E
被使用了吗?[SUDO] CMD: sudo -E ls …
没问题。解释器是
bash
,而不是sh
,因为我选择使用@Q
来打印引用的参数以避免歧义。或者它可能是printf '%q ' sudo "$@" >/dev/tty
。这两个变体可能会给出不同的(但等效的)输出,因此请选择您更喜欢的那个。脚本可能会
$PATH
自行更改;或者它可以sudo
通过其完整路径调用真实路径。因此它可能会绕过包装器。real
sudo
足够智能,可以等待另一个sudo
使用同一终端的用户。换句话说:两个sudo
insudo foo | sudo bar
不会同时要求您输入密码。我们的包装器没有那么智能,两个并行启动的包装器可以并行打印。
包装器并不是一个完美的解决方案。
聚丙烯酰胺
如果您的sudo
用途聚丙烯酰胺,可以在询问您的密码之前让它执行一个脚本。
在尝试做任何事情之前,请先读到最后。
注意:本节中我们要做的几乎每件事都需要sudo
一个提升权限的 shell ( sudo -i
)。您应该启动至少一个提升权限的 shell 并保持其运行,直到完成所有更改后您(作为普通用户)确认您的sudo
计算机仍然正常工作。如果您(我们)以某种方式设法破坏了您的计算机,shell 将会成为您的救星sudo
。
将以下代码另存为/usr/local/bin/sudo_pam_script
并使文件可执行。该文件应属于root:root
并且其模式应为rwxr-xr-x
。这是代码:
#!/bin/bash
printf '[SUDO] PWD: %s\n' "$PWD"
printf '[SUDO] CMD: '
</proc/"$PPID"/cmdline mapfile -d '' arg
printf '%q ' "${arg[@]}"
exit 0
编辑/etc/pam.d/sudo
并在所有未注释的行之前添加以下行:
auth optional pam_exec.so stdout /usr/local/bin/sudo_pam_script
从现在起,sudo
如果脚本要求输入密码,您将运行该脚本。但如果不要求输入密码,它就不会执行此操作。
笔记:
此解决方案是全球性的,它影响所有 sudoers,他们无法轻易选择退出。
我不太了解你的操作系统。你标记了Linux的,所以
/proc
可能存在(但一般来说不必存在)。您sudo
可能会或可能不会使用 PAM,或者其配置可能会产生干扰。我在 Kubuntu 中测试了该解决方案。>/dev/tty
不是必需的。sudo
它本身应该重定向(或者说中继)脚本的输出。您可以
printf '%q ' "${arg[@]}"
使用printf '%s ' "${arg[@]@Q}"
。尝试两者并选择其中一个。就 而言,此解决方案比包装器更好
sudo foo | sudo bar
。但您不会将整个管道视为一个命令,因为每个命令sudo
只知道自己的部分。在我的 Kubuntu 中,该解决方案不适用于
sudo -i
。有一个单独的文件/etc/pam.d/sudo-i
与此案例相关。