我有 2 个 CentOS 系统,通过 ssh 连接到。在其中一个上,如果我从剪贴板粘贴多个命令,它会执行所有命令,除非其中有 sudo 命令。如果有,它就会执行该操作,并跳过所有其他命令。例如。:
$ echo aa
sudo echo bb
echo cc
结果:
aa
bb
无论哪个 sudo 命令,无论之前或之后有多少命令。
bind -v
的enable-bracketed-paste
设置为off
另一个例子:
$ sudo echo dd ;\
echo ee
echo ff
结果:
dd
ee
其他 CentOS 则不会出现这种情况。为什么会发生这种情况以及如何修复而不修改粘贴的命令?
编辑: 发现它ksh
不会发生。我无法安装其他外壳进行测试。
答案1
这看起来像是标准输入无意消耗的情况。
您在交互式会话中粘贴的任何内容都是当时在前台运行的命令可用的标准输入数据,并且通常由您可能按顺序运行的所有命令共享(并可用),无论速度有多快(或慢)您也许可以输入/粘贴。每个命令都有机会使用其执行时恰好可用的部分或全部标准输入数据。
sudo
确实是那些将主动地执行的命令之一吃完 全部它的标准输入如果它被配置为这样做,这很可能是出于安全原因,特别是在企业设置中。如果您是这种情况,则sudo
正在使用您粘贴的任何文本(即后续命令)。
如果您被允许查看/etc/sudoers*
您遇到该行为的主机的文件,请检查它们是否可能有一个或(或什至两者)的Defaults
行设置,或者可能是您的帐户或组,或者即使只是对于您正在运行的确切命令。事实上,如果系统管理员如此倾向于的话,它实际上甚至可能是 中设置的其他系统范围的插件(不太可能,但有可能)。use_pty
log_input
ALL
sudo
/etc/sudo.conf
无论如何,您应该能够通过简单地将粘贴内容包装在子 shell 中来解决该问题:
(只需在您使用的任何 shell 的常规提示符下键入左括号,然后按 即可Enter。您将看到所谓的“PS2”(又名“需要更多输入”)提示符,通常是>
,您可以在其中随意键入命令,当然也可以按原样从剪贴板粘贴它们。这些命令不会立即运行,而是会在由左括号启动的子 shell 中“排队”,直到您显式结束它为止。完成键入/粘贴后,通过键入右括号)并再次键入 来完成Enter,这将结束子 shell。
sudo
只有到那时,您粘贴的命令才会最终运行,而不会被其中任何一个(或其他)可能按照其正常(或特殊)行为消耗标准输入的命令“吃掉” 。这是因为所有相关的标准输入(即您的粘贴)都已经被“排队”子 shell 消耗掉了,因此sudo
没有什么可以“吃掉”的。
最后请注意,在你的情况下enable-bracketed-paste on
会成为你的朋友,因为这本质上使bash
检测粘贴的文本,将其与打字的文本,由终端仿真器辅助(只要终端仿真器确实提供此类功能)。
至于为什么ksh
看起来“正确”工作的原因,我还没有深入研究它的内部结构,但是,乍一看strace
,它似乎正在阅读缓冲量的标准输入,可能会将其标记为单个命令来逐一运行,而不是以典型的简化方式读取和执行标准输入。
至于完全screen
忽略enable-bracketed-paste on
,我自己并不是一个狂热的用户screen
,但我可以说:这显然是一个非常“丰富”的终端软件,它可能行为bash
作为终端仿真器本身,因此它可能会干扰(例如忽略和剥离)为括号粘贴功能向终端仿真器发送/从终端仿真器接收的转义码。
答案2
此行为可能与将命令序列粘贴到终端时 shell 如何解释命令序列有关。一种可能的解释是,观察到此行为的系统上的 shell 将整个命令序列解释为一行,并且该sudo
命令导致 shell 在执行其余命令之前退出。
为了避免修改粘贴的命令并解决此问题,您可以尝试以下几种方法:
使用不同的 shell:正如您所提到的,使用 Korn shell (ksh) 时不会出现此问题。您可以尝试使用不同的 shell(例如 Bash 或 Zsh)来查看行为是否发生变化。
使用子shell:您可以将命令分组到子shell中,然后使用来
sudo
执行子shell。这将确保所有命令都在子 shell 内执行,无论命令是否sudo
退出 shell。例如:
$ (echo aa ; echo bb ; echo cc)
$ sudo sh -c '(echo aa ; echo bb ; echo cc)'
请注意,子 shell 方法可能并非在所有情况下都有效,特别是如果粘贴的命令包含复杂的语法或变量扩展。
如果这些方法都不起作用,您可能需要修改粘贴的命令以确保命令以正确的顺序执行。例如,您可以将命令序列分解为多行,或者使用 shell 脚本按所需顺序执行命令。
答案3
我冒昧地猜测,您的 shell readline
、PS1
提示符或PROMPT_COMMAND
中的某些内容会丢弃其中的待处理字符标准输入。
尝试输入这两行无需等待第一个完成:
sleep 10
id
如果id
不执行,那么您需要更仔细地调查环境。