0

I have this makefile:

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

Running watch (or any other process that somehow changes the terminal) ruins the terminal. This is the output. You can see these big spaces. Also, I can't see the characters afterwards, when I write:

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

Is there a way to prevent a process changing the terminal?
A clarification: watch is just a reproductible example. I'm using another app that should run as daemon, but still ruins the terminal.


Edit: I start this app (on this example, the app is watch) with sudo
A workaround is to start it without sudo - then the terminal isn't ruined.
The disadvantage in that is, that I need to chown this process to not be root:root.

7
  • 4
    Yes. Don't run an inherently interactive process in the background Sep 11, 2022 at 13:53
  • @roaima how does this comment helps? This is an example. I run a process, which apparently do something to the terminal.
    – hudac
    Sep 11, 2022 at 15:44
  • You're running a process (watch) that is designed to be run as an interactive process in the foreground that takes over and uses the entire terminal screen Sep 11, 2022 at 16:21
  • watch was an example for a process who changes the terminal. This is a reproducible example that one can take and modify -> in case this issue is solvable. Are reproducible examples wrong?
    – hudac
    Sep 11, 2022 at 18:11
  • Reproducible examples are great. The premise still stands though: don't run a tool that expects to control the entire screen in the background. watch is one example. vi[m] would be another except that it cleanly refuses to run at all if pushed the background. nethack might be another but I don't have it installed. Sep 11, 2022 at 18:15

3 Answers 3

3

watch by design updates the terminal. It "watch"es an object, and displays the current version of that object (or changes to that object with -d). An example of where watch is useful, is if you wanted to monitor the temperature of the cpu you can open a new terminal, and run the below command, the output would update every 2 seconds with the temp recorded by the sensor.

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

I am unsure why you would want to watch "ls -l" You could create a shell script that logs the output?

#!/bin/bash

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

if you are wanting to log new files, or modified files then:

 #!/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

You may want to increase the sleep time, I made it 2, as that is the default for watch.

The reason that the output is indented, and you can not see characters you type after the output, is due to your terminal not Bash.

Check your settings on your terminal program and also check termtype to ensure they match encoding (eg: utf8, ANSII etc) the terminal is only moving the cursor down a line (\n), and not resetting the cursor back to the start of the line (\r). This can also occur if the file was created in windows then moved to linux, or created in linux and moved to windows.

The characters you type are being displayed behind the last line of the output. Therefore you can not see it.

4
  • +1. correct, except for one detail: watch actually doesn't "watch for changes", it just repeatedly clears the screen, runs whatever you tell it to and displays the output.
    – cas
    Sep 11, 2022 at 14:52
  • watch was just an example for an app that changes the terminal. I use another app that do that. This app runs as daemon and still it ruins the terminal.
    – hudac
    Sep 11, 2022 at 15:46
  • @cas watch -d most definitely watches for and identifies changes Sep 11, 2022 at 16:33
  • @roaima and none of the examples here uses watch's diff mode (which still doesn't "watch for changes", it highlights the diff between the current run and either the previous run or, with -d=permanent, the first run).
    – cas
    Sep 11, 2022 at 23:58
2

Is there a way to prevent a process changing the terminal?

Not really. The terminal state is global to the terminal and can be changed by any process that has permission to do so.

$ 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;

As an exercise you can figure out how to undo that change. Another exercise is to see what shells or programs honor erase being the traditional # (as seen in "The UNIX Programming Environment" (1984)).

Interactive programs are otherwise not designed to run in the background and even if they do not alter the terminal state their output may be interleaved with output from other programs and hard to read, or they may forever be being hit with SIGTTIN or SIGTTOU signals as they try to interact with the terminal from the background. Stair-stepping is a common problem where the terminal state (or a line printer) is out of sync with what a process expects it to be; there are various flags that influence CR/NL handling documented in the termios manual page (INLCR, IGNCR, etc). If your background process expects setting X but the shell changes it back to Y, well, then you have a conflict.

Some operating systems might have security frameworks that might let you prevent a program from changing the terminal settings. In this case the interactive program may not run or may fail to operate as designed, and you may end up spending quite a lot of time fiddling around with the security framework to get the configuration just right.

Another option may be to run the process under a unique pty (e.g. under tmux) where it should not interfere with other programs being run in other windows.

stty -g (if supported) will let you save (some of) the terminal settings to be restored at some later time, but this will not work if a process in the background is forever fiddling with the terminal state, or if the settings the background program needs conflict with the restored values. Most programs only make terminal state changes at startup or at other specific events (reacting to control+z and then when being brought into the foreground, for example). A program could use tcsetattr(3) to fiddle with the terminal state directly.

Some shells are better than others at restoring the terminal state after a program exits. Compare ZSH with, say, the Heirloom Bourne Shell. Various programs will ignore certain terminal settings, e.g. ZSH will ignore erase being set to #, while under other programs (cat, for example) # should erase the previous character.

Exercise hint: lnext short for "literal next" is usually control+v, or whatever stty -a says it is. Programs may not honor this...

0
  • For either watch or your daemon, you can try redirect stdin i.e. add < /dev/null as well, so it never gets access to your terminal in the first place.
  • And you're saying it's a daemon, so the other way is run it from your systemd or init, again to keep it from touching your tty
  • If this was just a test and you need to recover, there is also stty sane
3
  • Thanks for the answer: I've already tried < /dev/null - it didn't work. It is a daemon that get started using systemd. But I currently start it in development environment inside a docker container where I don't have systemd, so I need to start it manually. stty sane - should I run it afterwards, like reset?
    – hudac
    Sep 12, 2022 at 7:06
  • exactly - try typing it when you need things to be back to normal again Sep 12, 2022 at 9:07
  • I want them to not get ruined at all. I'm not sure what's the point of this process I start, that it messing with the terminal. I edited my question - I wrote that when I start this process with sudo it happens. But if I start it without sudo it does not happen
    – hudac
    Sep 12, 2022 at 9:12

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .