当 ssh 运行 时,来自后台进程的换行符不起作用

Newlines from a background process aren't working while ssh is running

我有一个进程在后台打印一些文本行 运行。如果我启动 ssh,换行符将无法正常工作。

user@localhost:~$ { sleep 5; echo -e "1\n2\n3" ; } &
[1] 26215
user@localhost:~$ 1
2
3
user@localhost:~$ { sleep 5; echo -e "1\n2\n3" ; } &
user@localhost:~$ ssh localhost # quickly
user@localhost:~$ 1
                   2
                    3

无论 ssh 是否 运行,我都希望 2 和 3 在换行符的开头开始。有人可以解释这里发生了什么吗?有没有办法解决问题,使换行符仍然有效?

奇怪的是,如果我将一些 \r 混入其中,换行符似乎又可以工作了,尽管我也需要用 \r 替换默认的 echo 换行符。

user@localhost:~$ { sleep 5; echo -en "1\r\n2\r\n3\r\n" ; } &
[1] 7066
user@localhost:~$ 1
2
3

默认情况下,在交互式 shell 中,tty/pty 处于 canonical 模式,写入 tty 的 \n 将自动转换为\r\n.

当您通过 ssh 连接到远程服务器以启动交互 shell 时,ssh 会将本地 tty 更改为 raw 模式(或非规范模式)并在原始模式 \n 不会转换为 \r\n.

参见以下示例(突出显示了 ^ 个字符的部分):

[BASH] # tty
/dev/pts/2
[BASH] # stty -a -F /dev/pts/2
speed 38400 baud; rows 43; columns 80; line = 0;
intr = ^C; quit = ^\; erase = ^H; kill = ^U; eof = ^D; eol = <undef>;
eol2 = <undef>; swtch = <undef>; start = ^Q; stop = <undef>; susp = ^Z;
rprnt = ^R; werase = ^W; lnext = ^V; discard = ^O; min = 1; time = 0;
-parenb -parodd -cmspar cs8 -hupcl -cstopb cread -clocal -crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff
-iuclc ixany -imaxbel iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
^^^^^               ^^^^^
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt
     ^^^^^^
echoctl echoke -flusho -extproc
[BASH] #
[BASH] # ssh -t 127.0.0.1 bash --norc
bash-5.1# tty
/dev/pts/13
bash-5.1# stty -a -F /dev/pts/2
speed 38400 baud; rows 43; columns 80; line = 0;
intr = ^C; quit = ^\; erase = ^H; kill = ^U; eof = ^D; eol = <undef>;
eol2 = <undef>; swtch = <undef>; start = ^Q; stop = <undef>; susp = ^Z;
rprnt = ^R; werase = ^W; lnext = ^V; discard = ^O; min = 1; time = 0;
-parenb -parodd -cmspar cs8 -hupcl -cstopb cread -clocal -crtscts
-ignbrk -brkint ignpar -parmrk -inpck -istrip -inlcr -igncr -icrnl -ixon -ixoff
-iuclc -ixany -imaxbel iutf8
-opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
^^^^^^
-isig -icanon -iexten -echo -echoe -echok -echonl -noflsh -xcase -tostop -echoprt
      ^^^^^^^
echoctl echoke -flusho -extproc
bash-5.1#

如您所见,要强制执行 \r\n 行为,您可以显式使用 \r\n:

printf '1\r\n2\r\n3\r\n'

您可以查看 stty 的 manual 以了解有关 misc 标志的更多详细信息。