Search code examples
macosunixstty

Why does ‘stty -echo’ not turn off the echo bit on macOS


I am reading Understanding Unix/Linux Programming by Bruce Molay. In Chapter 5, the book introduces a new command stty which can help you configure your terminal setting.

One example mentioned in the book is to use stty -echo to turn off the echo, then I tried it on my Mac but found it doesn't work at all.

// here is some infomation about my mac
Mac mini (M1, 2020)
OS version: 11.4

// by the way, I also tested it on my old intel mac, and I got the same result
Macbook Pro(Early 2015)
OS version: 10.15.6
// here are the commands I used in the terminal on Mac
➜  ~ stty -a # check the old 'echo bit' status
speed 38400 baud; 45 rows; 139 columns;
lflags: icanon isig iexten echo echoe echok echoke -echonl echoctl
    -echoprt -altwerase -noflsh -tostop -flusho pendin -nokerninfo
    -extproc
iflags: -istrip icrnl -inlcr -igncr ixon -ixoff ixany imaxbel iutf8
    -ignbrk brkint -inpck -ignpar -parmrk
oflags: opost onlcr -oxtabs -onocr -onlret
cflags: cread cs8 -parenb -parodd hupcl -clocal -cstopb -crtscts -dsrflow
    -dtrflow -mdmbuf
cchars: discard = ^O; dsusp = ^Y; eof = ^D; eol = <undef>;
    eol2 = <undef>; erase = ^?; intr = ^C; kill = ^U; lnext = ^V;
    min = 1; quit = ^\; reprint = ^R; start = ^Q; status = ^T;
    stop = ^S; susp = ^Z; time = 0; werase = ^W;
➜  ~ stty -echo # turn off echo bit
➜  ~ stty -a # see the results
speed 38400 baud; 45 rows; 139 columns;
lflags: icanon isig iexten echo echoe echok echoke -echonl echoctl
    -echoprt -altwerase -noflsh -tostop -flusho pendin -nokerninfo
    -extproc
iflags: -istrip icrnl -inlcr -igncr ixon -ixoff ixany imaxbel iutf8
    -ignbrk brkint -inpck -ignpar -parmrk
oflags: opost onlcr -oxtabs -onocr -onlret
cflags: cread cs8 -parenb -parodd hupcl -clocal -cstopb -crtscts -dsrflow
    -dtrflow -mdmbuf
cchars: discard = ^O; dsusp = ^Y; eof = ^D; eol = <undef>;
    eol2 = <undef>; erase = ^?; intr = ^C; kill = ^U; lnext = ^V;
    min = 1; quit = ^\; reprint = ^R; start = ^Q; status = ^T;
    stop = ^S; susp = ^Z; time = 0; werase = ^W;

Then I tested it in an ubuntu docker container, and stty -echo worked perfectly.

So why does it not work on macOS?


Solution

  • Interactive shell retains some controls over stty setting.

    In Ubuntu, you are using bash, whereas in MacOS, you are using zsh.

    As a test, run /bin/bash in MacOS and do your test.

    Update

    Interactives shells do not effect stty's behavior, they can change tty's attributes equivalent of stty echo, just before displaying prompt.

    You can verify this by running in zsh :

    stty -a; stty -echo; stty -a
    

    To ask zsh not to do stty echo, you can do :

    unsetopt ZLE
    

    But this disables zsh's editing capabilities, which is not what you want.