Shell 为什么在使用zsh小部件执行交互命令时会中断

Shell 为什么在使用zsh小部件执行交互命令时会中断,shell,zsh,Shell,Zsh,Zsh版本: zsh 5.4.2(x86_64-ubuntu-linux-gnu) 代码(两个文件:.zshrc和interactive,都位于我的主目录中): .zshrc: source ./interactive custom_execute(){ echo exc0 $BUFFER BUFFER="" zle accept-line } zle -N custom_execute bind_enter(){ bindkey '^M' custom_execute }

Zsh版本:

zsh 5.4.2(x86_64-ubuntu-linux-gnu)

代码(两个文件:.zshrc和interactive,都位于我的主目录中):

.zshrc:

source ./interactive

custom_execute(){
  echo
  exc0 $BUFFER
  BUFFER=""
  zle accept-line
}
zle -N custom_execute
bind_enter(){
  bindkey '^M' custom_execute
}
交互式:

exc0(){
  echo exc0_begin
  cmd="$@"
  eval "$cmd"
  ret=$?
  echo exc0_end
  return $ret
}
情景:

打开新shell,执行以下命令:

exc0 sudo apt remove gparted
exc0之后执行什么命令并不重要,重要的是它需要用户在完成之前从stdin输入。在我的例子中,安装了gparted,它会询问我是否要删除它

我使用ctrl+c终止命令,因为我并不真的想删除gparted。 最后一行是:

Do you want to continue? [Y/n] ^C%
现在我输入以下命令:

bind_enter
之后:

sudo apt remove gparted
最后两行显示:

Do you want to continue? [Y/n] Abort.
exc0_end

在这两种情况下,shell都会询问我的sudo密码,该部分正在工作。但当涉及到确认时,第二个命令中断。问题:为什么?

如果直接从TTY读取(如
sudo
password entry)有效,但从stdin读取(如常规提示)无效,那么您可以通过将TTY重定向到stdin来解决这一问题,以获得应该从TTY读取的特定命令

因此:

exc0(){
本地网
回声exc0_开始

“$@”这不是您当前问题的原因,但是
cmd=“$@”;eval“$cmd”
通常有错误--
“$@”
是一个数组,不能毫无损失地转换为字符串。为了向您自己证明这一点,请尝试运行以下命令:
设置--printf“%s\n”第一行“第二行”;cmd=“$@”;eval“$cmd”
…将其与正常运行的代码
集--printf“%s\n”第一行“第二行”;“$@”
,或同样正常运行的
集--printf“%s\n”第一行“第二行”;cmd=(“$@”);“${cmd[@}”
,或与同样正常运行的
集--printf“%s\n”第一行“第二行”进行比较;printf-v cmd“%q'”$@;eval“$cmd”
。无论如何,就
sudo
密码和其他输入之间的差异而言,请使用
@CharlesDuffy I将eval“$@”替换为eval“$@” $@谢谢你的回答。我试着用“$@”。啊!在这种情况下,您的代码将作为单个参数传递,而不是每个单词一个参数,因此您可以
eval“$1”至于查看您键入的内容,配置本地echo是stty
的一项工作。请确保您在
/dev/tty
上给它一个要操作的文件句柄。我最后保存了.zshrc中开始的tty配置,并将eval行更改为eval“stty$stty\u CONFIG;$cmd”exc0() { local ret echo exc0_begin "$@" </dev/tty; ret=$? echo exc0_end return "$ret" }