当从 ~/.zshrc 执行 sudo 函数时,“找不到命令”

当从 ~/.zshrc 执行 sudo 函数时,“找不到命令”

我的 中有一个函数~/.zshrc

findPort() {
    lsof -t -i :$1
}

通常的调用是findPort 3306.

我想以更高的权限运行它。但我得到“命令未找到”。

➜  git 

答案1

sudo直接运行命令,而不是通过 shell,即使它运行一个 shell 来运行该命令,它也将是一个新的 shell 调用,而不是读取您的命令~/.zshrc(即使它启动了一个交互式 shell,它可能会root读取~/.zshrc,不是你的,除非你配置sudo为不重置$HOME变量)。

在这里,您需要告诉sudo启动一个新的zshshell,并告诉它在运行该函数之前zsh读取您的~/.zshrc内容:

sudo zsh -c '. $0; "$@"' ~/.zshrc findPort 3306

或者:

sudo zsh -c '. $0; findPort 3306' ~/.zshrc

zsh或者与调用的新函数共享当前的 zsh 函数sudo

sudo zsh -c "$(functions); findPort 3306"

虽然你可能会得到一个arg 列表太长如果定义了很多函数(例如使用完成系统时),则会出现错误。因此,您可能希望将其限制为该findPort函数(以及它所依赖的所有其他函数(如果有)):

sudo zsh -c "$(functions findPort); findPort 3306"

你还可以这样做:

sudo zsh -c "(){$functions[findPort]} 3306"

将函数的代码嵌入findPort匿名函数您将 3306 参数传递给它。甚至:

sudo zsh -c "$functions[findPort]" findPort 3306

(内联脚本传递给-c 函数体)。

您可以使用辅助函数,例如:

zsudo() sudo zsh -c "$functions[$1]" "$@"

不使用:

sdo() { sudo zsh -c "(){$functions[$1]} ${@:2}" }

因为 的参数sdo将经历另一个级别的 shell 解析。比较:

$ e() echo "$@"
$ sdo e 'tname;uname'
tname
Linux
$ zsudo e 'tname;uname'
tname;uname

答案2

对我来说,一个非常简单的解决方案是使用 调用交互式 shell sudo -s,它似乎适用于我的 macOS 捆绑版本的 zsh (5.2)。这为我提供了我的~/.zshrc.

从 sudo 手册页来看,它并没有真正暗示这种行为:

-s, --shell
运行由 SHELL 环境变量指定的 shell(如果已设置)或由调用用户的密码数据库条目指定的 shell。如果指定了命令,则会通过 shell 的 -c 选项将其传递到 shell 执行。如果未指定命令,则执行交互式 shell。

我不确定您的用例是什么,但我怀疑您正在寻找交互式解决方案。

答案3

我能够制作一个可重复使用的速记对于 Stéphane Chazelas 中描述的解决方案之一回答。 [编辑:Stéphane 迭代了我提出的原始快捷方式;这里描述的代码是他制作的更新版本]

将其放入您的~/.zshrc

sdo() sudo zsh -c "$functions[$1]" "$@"

现在您可以用作sdosudo仅用于用户定义的函数”。

要确认其sdo有效:您可以在打印您的用户名的用户定义函数上进行尝试。

➜ birch@server ~/ 

答案4

这似乎对我有用:

function sudo (){
  args="$@"
  /run/wrappers/bin/sudo -u "$USER" zsh -i -c "$args"
}

相关内容