手头上的问题

手头上的问题

我将以下 100 行复制/粘贴到我的终端 (xterm) 中,以在我连接到的服务器上执行这些行ssh

mv /long/path/to/file1 /longer/path/to/file1
mv /long/path/to/file2 /longer/path/to/file2
...
mv /long/path/to/file99 /longer/path/to/file99
mv /long/path/to/file100 /longer/path/to/file100

不幸的是,复制/粘贴后,我找不到我的 100 个文件/longer/path/to/

查看我通过 ssh 连接的服务器上的 bash 历史记录,我可以看到在前 20 个命令之后,大多数命令都被截断了:

mv /long/path/to/file1 /longer/path/to/file1
...
mv /long/path/to/file20 /longer/path/to/file20
mv /long/path/to/fi
mv /long/path/to/fi
mv /long/path/to/file23 /longer/p
mv /long/path/to/file24 /longer/path
mv /long/path/to/file25 /longer/p
mv /long/path/to/file26 /longer/p
mv /long/path/to/file27 /longer/path/t
mv /long/path/to/file28 /longer/path/to/fil
mv /long/path/to/file29 /longer/path/to/fil
mv /long/path/to/file30 /longer/path/to/file
mv /long/path/to/file31 /longer/path/to/file
...

我可以找到有关如何解决此问题的答案:

但我找不到对到底发生了什么的解释。尤其:

  • 这是一个与终端相关的问题(在我的例子中是 Xterm)?
  • 复制/粘贴发生在ssh:这是否会产生或放大问题?
  • 这是服务器上与 bash 相关的问题吗?如果使用另一个外壳,可能不会发生这种情况吗?

答案1

看来你遇到了这个错误:

https://lkml.org/lkml/2013/7/25/205

当粘贴超过 4k 超出行规则缓冲区时,readline() 会无意中触发错误恢复路径。当行规则缓冲区已满并在规范模式下运行且未收到换行符时,错误恢复路径会丢弃输入。由于 readline() 将 termios 更改为非规范模式以逐个字符读取行,因此行规则缓冲区可能会变满,然后当 readline() 将 termios 恢复为调用者的规范模式时,现在已满行规则缓冲区触发错误恢复。

当将 termios 从非 canon 模式更改为 canon 模式并且读取缓冲区包含数据时,模拟 EOF 推送没有读取缓冲区中的 DISABLED_CHAR。

对于 readline() 问题,重要的是,termios 可以更改回非规范模式,而无需更改读取缓冲区;即,就好像之前的 termios 更改没有发生一样(只要没有发生干预读取)。

它于 2013 年 12 月 10 日应用于内核,即 Linux 内核 3.14。您是否正在使用比它更旧的 Linux 发行版?您的发行版是什么?您可能将实际路径替换为文件,因此我无法真正计算字符数。您可以这样做:

for ((a=1; a<20; a++)); do echo "mv /long/path/to/file$a /longer/path/to/file$a"; done|wc -c

与你的真实路径 - 它会是真正接近 4k 的东西吗?如果是这样,上面的错误可能是你的。

如果是这样,请回答您的问题:

  • 这是一个与终端相关的问题(在我的例子中是 Xterm)?

  • 复制/粘贴通过 ssh 进行:这是否会产生或放大问题?

  • 这是服务器上与 bash 相关的问题吗?

不,是的 - 这不是 bash 或 bash 使用的任何库中的错误。 Bug 存在于内核中。

  • 如果使用另一个外壳,可能不会发生这种情况吗?

可能是,如果 shell 不使用 readline。就像 zsh 一样。

关于相关问题“如何粘贴多个...”似乎与您的问题无关 - 原因是某些应用程序可能会读取您粘贴的命令。最著名的例子是 ssh,如果您在远程服务器上运行 ssh 命令。但考虑到你只丢失了部分线路,在你的情况下这是不可能的。

第二个问题“命令粘贴到终端...”于 2013 年 9 月 25 日提出,当时补丁不存在,这绝对看起来像您遇到的错误,并且我怀疑我是内核错误。

如何检查确定?将 uname -a 的输出粘贴到此处。

答案2

手头上的问题

您希望了解为什么复制和粘贴的代码行被截断。

我研究了你的问题,发现 Bash 默认情况下通常有行限制。这很可能是你的问题。但是,您给出的示例显示行被以不同长度截断。我会尽力打破这个局面。

解决方案

1.这是一个与终端相关的问题(在我的例子中是Xterm)?

很可能是这样,但这是由于默认 Bash 环境而不是 xterm 的限制。 (除非你改变了xterm的许多默认值)

我引用以下帖子,这些帖子提供了增加行长度以希望减少截断的解决方案。这个 U&L 堆栈交换答案涵盖更改窗口大小以匹配终端仿真器的期望。用户saketrp 提供了这个解决方案,以确保您的终端正确解释您的窗口大小。

如果你使用的是bash,你可以尝试这个。

$ shopt checkwinsize

如果你没有得到

checkwinsize    on

然后激活它

$ shopt -s checkwinsize

然后尝试运行另一个命令(如 ls)或调整窗口大小一次,以上每次都对我有效。

特别是对于 Redhat 系统,该问题通常是由于错误配置 ~/.bashrc 而不调用 /etc/bashrc 引起的。通常,bash 加载 ~/.bashrc,预计会调用 /etc/bashrc,默认情况下包含 shopt -s checkwinsize。

然而,这仅影响窗口大小的解释,而不影响实际行长度。使用中提供的信息这个 AskUbuntu 帖子如果您shopt设置正确,您可以添加以下行来.bashrc增加行长度。

COLUMNS=250

并运行source .bashrc以更新您的 Bash 配置文件。

2. 复制/粘贴通过 ssh 进行:这是否会产生或放大问题?

我想说,这即使不是根本原因,也是问题的一部分。您链接的解决方法是防止这种情况发生的可靠解决方案。

我建议,如果您需要复制并粘贴一组命令(您是否需要多次使用它们?),请创建该组命令的 Bash 脚本。然后使用scp、、、sftp电子邮件curl或任何方法远程传输您想要使用的文件。

这完全避免了链接解决方法中概述的截断问题,您甚至可以同时编写脚本的创建和/或传输到许多服务器的脚本。

3.服务器上是否存在与bash相关的问题?如果使用另一个外壳,可能不会发生这种情况吗?

如前所述,是的,这可能是 Bash 配置文件设置设置的行限制的问题。其他 shell 可能没有这个问题,但我自己只熟悉 Dash/Bash。但是,如果这些是生产服务器或遗留系统,那么如果您开始更改环境变量,它可能并不总是有效。并不是说这并非不可能,但是如果某些软件包/软件/以前的脚本/cronjobs 依赖 Bash 作为默认 shell,则存在风险,更改此设置可能会产生后果。

再次,我建议您创建一个您想要运行的命令的脚本,并将其传输到远程服务器以在那里运行,以解决此问题。

结论

命令被截断的原因取决于您的环境、Bash 配置文件设置、终端仿真器设置以及复制和粘贴命令的方法。正如您所指出的,有一些解决方法,我建议您将它们与脚本结合使用以避免出现问题。我还包括一个链接到xterm联机帮助页这样您就可以查看是否有任何其他设置或选项可以更改。

如果您对此答案有任何疑问或疑问,请发表评论。我感谢您提供反馈来纠正任何误解并改进我的帖子。我可以根据需要更新我的答案。

祝你好运!

答案3

我建议使用 gzip 和 base64 将命令从一个终端复制到另一个终端。如果问题来自元字符或制表符扩展,您应该以这种方式解决它。

例子:

[root@server-one ~]# cat << __EOF__ | gzip | base64
mv /long/path/to/file23 /longer/p
mv /long/path/to/file24 /longer/path
mv /long/path/to/file25 /longer/p
<other commands>
__EOF__

然后将编码结果复制到

[root@server-two ~]$ base64 -di | gunzip | bash
<insert your base64-encoded and send with control-d>

相关内容