在后台运行的进程会破坏终端

在后台运行的进程会破坏终端

我有这个makefile

all: 
        sudo watch "ls -l" > /dev/null &
        @echo line 1
        @echo line 2
        @echo line 3
        @echo line 4

跑步watch或以某种方式改变终端的任何其他进程)破坏了终端。这是输出。你可以看到这些大空间。另外,当我写下以下内容时,我看不到这些字符:

me@me:/tmp$ make
watch "ls -l" > /dev/null &
line 1
line 2
      line 3
            line 4
                  me@me:/tmp$ 

有没有办法阻止进程更改终端?
澄清:watch只是一个可重现的例子。我正在使用另一个应作为守护进程运行的应用程序,但仍然会破坏终端。


编辑:我启动这个应用程序(在这个例子中,应用程序是watchsudo
解决方法是在没有 - 的情况下启动它sudo,那么终端就不会被破坏。
这样做的缺点是,我不需要chown这个过程root:root

答案1

Watch by design 更新了终端。它“监视”一个对象,并显示该对象的当前版本(或使用 -d 对该对象进行的更改)。 watch 有用的一个例子是,如果你想监控 cpu 的温度,你可以打开一个新终端,并运行以下命令,输出将每 2 秒更新一次,传感器记录的温度。

watch -x cat /sys/devices/pci0000:00/0000:00:18.3/hwmon/hwmon0/temp1_input

我不确定您为什么想要观看“ls -l” 您可以创建一个记录输出的 shell 脚本吗?

#!/bin/bash

while :
do 
   date +"%H:%M:%S" >> /var/log/ls.log
   ls -l >> /var/log/ls.log   
   sleep 2
done

如果您想记录新文件或修改的文件,则:

 #!/bin/bash
    
    while :
    do 
       find -newer /var/log/ls.log >> /var/log/ls.log
       date +"%H:%M:%S" >> /var/log/ls.log  
       sleep 2
    done

你可能想增加睡眠时间,我把它设置为2,因为这是手表的默认设置。

输出缩进并且您看不到输出后键入的字符的原因是您的终端而不是 Bash。

检查终端程序上的设置并检查术语类型以确保它们与编码(例如:utf8、ANSII 等)匹配。终端仅将光标向下移动一行 (\n),而不是将光标重置回行的开头行 (\r)。如果文件是在 Windows 中创建然后移动到 Linux,或者在 Linux 中创建并移动到 Windows,也可能会发生这种情况。

您键入的字符将显示在输出的最后一行后面。因此你看不到它。

答案2

有没有办法阻止进程更改终端?

并不真地。终端状态对于终端来说是全局的,并且可以由任何有权执行此操作的进程进行更改。

$ tty
/dev/ttys007
$ stty -a | grep ' erase'
        eol2 = <undef>; erase = ^?; intr = ^C; kill = ^U; lnext = ^V;
$ stty erase '#'
$ stty -a | grep ' erase'
        eol2 = <undef>; erase = #; intr = ^C; kill = ^U; lnext = ^V;

作为练习,您可以弄清楚如何撤消该更改。另一个练习是看看哪些 shell 或程序erase是传统的#(如“UNIX 编程环境”(1984 年)中所示)。

否则,交互式程序不是设计为在后台运行的,即使它们不改变终端状态,它们的输出也可能与其他程序的输出交错并且难以阅读,或者它们可能永远受到 SIGTTIN 或 SIGTTOU 信号的影响。尝试从后台与终端进行交互。阶梯式是一个常见问题,其中终端状态(或行式打印机)与进程期望的状态不同步;手册页中记录了影响 CR/NL 处理的各种标志termiosINLCRIGNCR等)。如果您的后台进程需要设置 X,但 shell 将其更改回 Y,那么您就会遇到冲突。

某些操作系统可能具有安全框架,可以让您阻止程序更改终​​端设置。在这种情况下,交互式程序可能无法运行或无法按设计运行,并且您最终可能会花费大量时间摆弄安全框架以获得正确的配置。

另一种选择可能是在唯一的 pty 下运行该进程(例如,在 下tmux),它不应干扰在其他窗口中运行的其他程序。

stty -g(如果支持)将允许您保存(某些)终端设置以便稍后恢复,但是如果后台进程永远在摆弄终端状态,或者如果后台程序需要设置,则这将不起作用与恢复的值冲突。大多数程序仅在启动时或在其他特定事件时(例如,对control+做出反应z,然后进入前台时)进行终端状态更改。一个程序可以使用tcsetattr(3)用来直接修改终端状态

有些 shell 在程序退出后恢复终端状态方面比其他 shell 更好。将 ZSH 与 Heirloom Bourne Shell 等进行比较。各种程序会忽略某些终端设置,例如ZSH将忽略erase设置为#,而在其他程序下(cat例如)#应删除前一个字符。

练习提示:lnext“字面下一个”的缩写通常是 control+ v,或者无论stty -a它是什么。程序可能不尊重这一点...

答案3

  • 对于watch您的守护程序,您也可以尝试重定向 stdin ie add < /dev/null,这样它就永远不会首先访问您的终端。
  • 你说它是一个守护进程,所以另一种方法是从你的 systemd 或 init 运行它,再次防止它接触你的 tty
  • 如果这只是一个测试并且您需要恢复,那么还有stty sane

相关内容