As a corollary, typing ^D twice on a non-empty line will also send EOF on the input, allowing you to provide a program with input not ending with \n from the command line. I knew about this behavior, but not why it worked, but this article's explanation clarifies this behavior as well. The first ^D terminates the read() call, passing the line so far, without terminating \n, to the program. The second causes read() to return with 0 read bytes, which is EOF, as explained in the article.
A super easy way to see this is to type cat, and then type asdf and hit ^D. It immediately echoes back what you typed. Another ^D quits cat, because it gets a 0-byte read that time.
I know this article says Unix specifically, but on Linux (Ubuntu) I just tried typing `ls^D` in bash and got a terminal beep. I tried in zsh and got an autocomplete as if I'd hit tab. In ksh and fish nothing happened. I'm curious as to why there are different behaviors here?
I believe your answer is in the article: "Note that modern shells are not good examples of this, because they don't do line-buffered input; to support command line editing, they switch terminal input into an uninterpreted mode. So they get the raw ^D and can do whatever they want with it, and they can let you edit as much of the pending line as they want."
As the article explained at the end, shells put the terminal into uninterpreted mode, so ^D doesn't do anything special there. You have to be using a program (such as cat) that doesn't do this to see ^D's behavior.
Actually bash (by default) does do something special with ^D: it's mapped to the "delete-the-char-after-the-cursor" functionality (just like the DEL key is), by analog to the delete-char binding in emacs.
But indeed, it's in raw mode so the kernel doesn't do anything special and just emits the 0x04 byte down the descriptor.
Shells that want to implement features like tab completion or more elaborate line editing than the basics, which only provide for deleting the last character, word, or line (using Backspace/^W/^U) need to put the terminal into raw mode when reading the user's command line so they can bypass the basic line editing that the terminal provides (called "cooked mode").
However, you can write a shell that doesn't do this. In particular, on Linux, you can experiment in dash. You'll find that the behavior is exactly the same as this article, since the terminal remains in cooked mode. In particular, if you type `l^Ds`, that will run `ls`, though you won't be able to delete the `l` anymore since that was input before the `^D`. Also, if you type `ls^D^D`, that will log out just like typing `^D` on an empty line does. Other shells have different behaviors -- for example, Bash seems to take `ls^D` to be the same as typing `ls` followed by pressing Enter.
Before any shell starts executing a program, however, it puts the terminal back in cooked mode no matter what mode it's in when at the prompt, since that's the default terminal mode expected by programs. If you want to experiment with the cooked mode line editing commands to get the behavior described in the article, you should run a command that receives standard input from the terminal (running `cat` by itself should suffice).
I didn't realize Dash uses cooked mode. That's actually kind of surprising; every other shell I've used always uses raw mode to give them more control over line editing. Is Dash just trying to be as minimalistic as possible?
Dash is really minimalistic. In its default mode, this is the only call to ioctl it makes on standard input according to strace:
ioctl(0, SNDCTL_TMR_TIMEBASE or SNDRV_TIMER_IOCTL_NEXT_DEVICE or TCGETS, {B38400 opost isig icanon echo ...}) = 0
Notice that it's merely calling TCGETS and that icanon is set, which means the "canonical input" mode with the default ^W/^U keybindings is enabled. Bash disables icanon so that it can enable line editing. Interestingly, dash seems to have vi and emacs editing modes, but they don't seem to cause dash to enter raw mode, so I'm not sure they do anything.
No TTY-related discussion is complete without a reference to Linus Akesson's extremely lucid article on the whole thing, including what all the other interesting Ctrl+ characters do:
Fun trick: If somebody is watching you type in your login password or SSH pubkey password, spaz wildly on the keyboard, frantically typing random characters, and then hit ^U and type in your real password.
Then you give them a puzzled look once you successfully log in as if nothing out of the ordinary just happened and say something like "What, don't you have a sufficiently complex password?".
> "What, don't you have a sufficiently complex password?"
<anecdote>
I actually had a sufficiently complex password, but this one time I was in a massive hurry to demo something to my teammates, I made a mistake somewhere near the end of it, quickly typed ^U, fed it all over again, made another mistake near the end, another quick ^U, and third time was the charm.
They didn't notice that I reset the password field twice, to them it was just a mega-super-duper-long password (the actual password is 20+ characters), and one of them burst out saying, "Woah! He just wrote a short story!"
</anecdote>
As long as you don't hit space you can do the same thing with ^W, as ^W will clear out the last 'word'. I use it all the time at password prompts, and more comfortable to hit than ^U.
In readline, ^U will only clear from the cursor to the start of the line, leaving anything on the right. ^K is the converse.
I'm not sure you are speaking about readline though.
Another very useful thing I use daily is Alt-F/B, to move forward/backward in the line one word at a time. Control does the same, one letter at a time. D will delete an element instead.
Emacs users will recognize many of the readline defaults -- unsurprisingly, given both are GNU software.
I use "yank-last-arg" most often, which is M-. by default.
$ mkdir abcd
$ cd <M-.>
On Zsh, I have M-, bound to "copy-earlier-word", which makes M-. M-, M-, cycle through the arguments to the previous command.
In reading the manpage for Bash, which doesn't have this function, I've just found "history-search-backward", which searches through history to find commands based on what you've already typed. That will come in useful!
Debian and Ubuntu typically have a commented-out mapping for this in /etc/inputrc as pgup/pgdn that I always enable in my ~/.inputrc. Editline supports something similar in .editrc IIRC.
Funny, I became FreeBSD user because default .cshrc contained it (iirc). I didn't know about shells, readline, etc. back then. Wonder why they do not enable it on up-down by default, cause I see too many linuxoids around bored with up-up-up-enter up-up-up-enter to replay history, not even knowing that completion exists (along with at least ^K ^U ^C).
What's the point to type a half-command and then replace input line with one from history if I press up? That somewhat resembles ugly cmd.exe, which every windows user imagines when someone says 'cli'.
Weird, I'd have thought C-r is the one readline command everybody knows even if they know nothing else abour readline. Almost cannot imagine using command line without it. (Though there's also the "like tab-complete but from history" that I never really learned to use.)
Yes some of these useful functions should be bound by default IMHO. Here are my settings to bind ctrl-{left,right} and {up,down} to more useful defaults. I.E. jump as the shell tokenizes the line, and search history for what's already typed respectively
For the vi-adherents out there, `set -o vi` will let you navigate your prompt and history with vi-like keybindings. I'm amazed by how many vi users don't know this.
To add to that, C-P will go up in your history and C-N down. It is extra useful when using GDB in TUI mode (which is activated using C-x,a), which will capture your UP/DOWN arrow to navigate the source...
Actually, just go read http://ss64.com/bash/syntax-keyboard.html or something, once per day, integrate a new one each time, and you will improve your productivity on the command line (as well as comfort).
For gdb TUI, you can also use the 'focus cmd' and 'focus src' commands to choose which window gets to handle up/down. I usually keep the command window focused out of habit because the source window intercepts too many keys for my liking.
Nice link - reminds me to try to use the history stuff like ! and ^ more.
I also find Ctrl-W for backspacing a word at a time useful and also Ctrl-A/E for jumping to the beginning and end of the current line.
Ctrl-L to clear the screen except the current line is also somewhat useful if you're at the bottom of the terminal screen and editing a long command line.
Somewhat less useful but neat is Alt-U which will cause the current word under the cursor to become all upper case and Alt-C which is similar but changes the first letter to upper case and the rest of the word to lower case.
To elaborate on yebyen's answer: these shortcuts can be handled in different layers of your stack. By default, ^U will be handled by your terminal emulator, and it will only delete the buffer, it won't remember what you've deleted. However, programs can ask the terminal emulator to pass ^U through to them so they can handle it themselves. This happens if you use libeditline (or libreadline), and these libraries implement a per-application buffer.
You can test this yourself. Type some text, then ^U, then ^Y. This works because your shell uses libreadline or libeditline. Try this again in a "dumb" program like cat, or a shell without line editing like /bin/dash. ^U works, but ^Y does nothing (well, it lets you type ^Y in as much as you want).
No, I don't think so. Not unless you are accustomed to typing your password directly into the terminal prompt. Kill buffers don't pass from one application to another and they don't all behave the same in every context, either.
(For example, if I type some stuff and then ^U to kill the password buffer at an SSH password prompt, typing ^Y after that seems to put the whole process in the background. Not sure what that's intended to do, but subsequent ^Y presses don't retrieve the password into the shell prompt...)
Actually, this is a feature of libreadline (in its default configuration). ^Y mimics the yank command from emacs. At an actual terminal input (like you can get by running `cat` with no arguments), ^Y will just echo back a literal ^Y (assuming it too is in its default configuration).
As someone else who also uses ^M for line return here's my reason.
I have the Caps key mapped to control, so ^M is 2 small finger movements as opposed to reaching for the return key which means either moving my (weak in my case) right wrist or moving my whole right forearm. It's a small movement to the return key but I find eliminating it really helps to reduce strain related pain when typing.
I also use ^H for backspace and ^I for tab for similar reasons. This also keeps my fingers on the home row.
I'm not proud of this, but I sometimes bounce between ^N (next-line in emacs) and ^I (tab character, bound to various thing in different emacs modes) to re-indent a region. I usually only do this for <10 lines. More than that and I go look up the function that does it 'right'.
^U is actually very convenient for clearing the current line when using the default mysql client. Still sometimes find myself at the command prompt after ^C because I'm used to psql.
Kidding of course, but once upon a time many 56k6 modem contained a bug that, upon receiving this in plain text, would cause an actual modem hangup. You could kill hundreds of IRC connections with that one.
It wasn't exactly an unintentional bug - rather one company owned a patent on the technique of enforcing a guard time before and after the attention string to go into command mode (the Hayes '302 patent). They licensed it for $1/modem, but some manufacturers felt that they couldn't afford that.
How did modems deal with pluses in data? Was there a way to escape the escape sequence, or was there just an ATSnnn or similar sequence to disable escapes?
There were a bunch of different mechanisms depending on vendor. Some required a specific time interval in between the + signs, so that typing very slowly, or instantly, wouldn't trigger the escape.
Some vendors had bugs in which when +++ appeared as part of the incoming data it would also trigger the firmware escape.
And of course programmable terminals had hilarious exploits where you'd get someone to run your program, it would program the terminal to emit a macro when you hit enter, the macro would include +++ATZ, etc., etc.
My favorite modem story was when I worked for a company that shipped auto parts warehouse management systems. They would have several SCO unix boxes with serial port concentrator cards and port concentrators on those concentrators, such that you'd have 256 modems on a single box and RS-232 cables everywhere. Frequently the operators at the auto parts warehouses couldn't be bothered to do cable management, so at one facility, the entire floor of the server closet was carpeted literally 2 feet thick with a random mess of RS-232 cables, each one leading to a modem. When standing on the cables killed a modem or two, they would just string a new wire rather than try to fish out the old one. Kind of like Google's "let it sit in the rack" policy for failed servers, but writ extremely small and pathologically badly.
The entire rack gets replaced with new equipment eventually. Probably get replaced every few years or so.
For most of the SMB clients I have, I don't build new servers any longer. I can buy rackmount servers pulled out of a data center that are a few years old at about 1/3 the price. I just put new disks in them and a new OS.
Many years ago, modem maker Hayes Microcomputer Products held a patent dealing with that issue. The clever bit was in looking for
<pause> +++ <pause>
to effect the escape.
Hayes tried to collect royalties, but this caused quite a kerfuffle. Cheap modem makers didn't bother looking for pauses. "Hilarity" ensued. Other solutions were found.
The author actually clouds what and why is really happening a bit. Ctrl+D sends the EOF character to the terminal driver. The terminal driver then determines, based on its settings, what to do next.
In the 'icanon' mode, the terminal driver implements a rustic line editor, so you can do things like Backspace to delete previous characters and so on. Pressing Enter during this mode returns the edited buffer line to the program.
Where Ctrl+D, or EOF, comes in is when you want to return a line to the program _without_ pressing Enter. This is where the terminal driver returns the buffer to the read() function for the program immediately. Doing it again with no additional input shows that you were done line-editing, so it simply returns nothing, signaling the program that you're done editing or providing input - the intended purpose of End Of File, the character sent by Ctrl+D. (If you were reading a file and you received nothing on a read... you would be at the end of a file, because why else would the file have nothing else to read?)
But this 'icanon' mode won't be active in your actual terminal shell, because shells have their own line editing implementation, so they turn 'icanon' off by default. You can, of course, turn on or off in the terminal with "stty". Use "stty -a" to see all the other current settings. The terminal application, by the way, sets the EOF to the same value as the terminal driver's by default, in order to prevent confusion.
I don't - and in fact I finally got around to creating a HN account in order to ask you. Googling that just leads me back to this discussion. What's it from?
If you have an ACM subscription, the sheet music was published in Communications of the ACM (Volume 27, Issue 4; April 1984): http://dl.acm.org/citation.cfm?id=1035691
It references "The TELNET Song" by Guy L. Steele (a.k.a The Great Quux). The original is about Telnet, and given the subject of discussion, the reference seemed a natural one to make.
I am not sure, but it looks vaguely familiar. There is a text-based game called adventure game called Dunnet where you come across a CPU card, and do some stuff with it later on. As far as I remember, the game predates SSH, so the game either had Telnet or FTP. My memory fades.
You'd probably trigger it more often if ~/ didn't conveniently map to ~/ - it's quite cleverly designed in a way. Indeed, most of the two-character combinations you're likely to type starting with ~ map to themselves.
Specifically, the escape sequence is "\n~", with various options (visible by typing "\n~?"), and if the option is unknown it passes the "\n~{x}" as-is.
The biggest false positive you'll see is "\n~v", when executing bins out of the home dir of a user starting with the letter 'v'.
Sadly it will shutdown only the 'outer' ssh session, so if you ssh to foo, and then from foo ssh to bar, and type ~. then the client->foo session is shut down but the foo->bar session is still around.
You need to type one ~ per session level toy want to reach and terminate. In your example, type ~~. to terminate the inner session, leaving the outer one live.
Those are yet more graceful -- for when the shell is responsive. Use ~. in cases where for some reason you cannot get access to the terminal anymore but remote sshd is responsive.
Actually the remote sshd does not need to be responsive, because "<cr>~." is interpreted by the local ssh client. Very convenient if the TCP connection is stuck.
You can also type "<cr>~?" for a list of other commands supported by the local ssh client. Among other things, "<cr>~C" opens a command line interpreter on the client side of the ssh client, allowing you to add and remove TCP port forwarding without restarting the connection.
Long ago I sent a patch for uploading downloading using this escape sequence, using zmodem like how an old windows SSH client (I forget the name) used to allow uploading/downloading files.
You log in, type "rz<enter>", and then use escape sequence to upload a file. (similar for downloading)
The patch was rejected. Shame. It's very useful when hopping 6 steps to upload a file.[1]
I can't find the patch now, but I'm considering rewriting it as a an `expect` script. My `expect` scripts tend to have trouble with SIGWINCH propagation though, so not optimal. Also you have to remember to wrap with the `expect` script at (and preferably only at) the one "jump" you want to send from/to with the final destination.
[1] No, nothing illegal. Just that some networks mandate SSH jumpgates, and sometimes multi-level.
~. (and the other ~ commands) are handled locally, not by the remote sshd. I use it when my network cuts out or something and my ssh session is unrecoverably stuck
iirc, enter-~-. isn't anything to do with the remote sshd. Instead, it escapes to the local ssh client (enter-~) that it should close (.). Which is really useful for if the remote sshd blew up, or, more commonly, your connection was broken.
In general, CTRL-anything send corresponding control character by shifting keys to control set of ASCII table [1] (shift-key shifts keys to upper set). Many of them retained original meaning, e.g. ^I ^M ^J ^H ^D ^[.
I wish articles like this would say what ^D means. I remember when I was new to Unix it took me a while to realize that I wasn't supposed to type a literal caret (^) followed by a D.
For reference it means Ctrl+D, unless you you have a strange keyboard from Sun or something.
^D is the old school way of writing it; you'd see it so much you'd only ever once be confused about it, generally in the very first few days you were learning to use a computer.
It's never used anymore, I suppose, except for the old school people who still have enough muscular memory built up to write it that way. I know I do; I learned it from some computer magazine in the 80's and have a hard time letting go.
I dunno if I'd say it was never used anymore. Try running `cat` (to bring up a basic termainal input) and type various control keys. Anything that isn't interpreted by the tty is probably displayed using caret notation.
> It's never used anymore, I suppose, except for the old school people who still have enough muscular memory built up to write it that way. I know I do; I learned it from some computer magazine in the 80's and have a hard time letting go.
I was born after the 80s, and I use that shorthand (although I suppose this probably says more about me than it does about the shorthand itself). I didn't even understand the original comment until I read through the whole thing because I mentally read it as "Ctrl+D"
I just tried to search for it as if I didn't know and it was hard. Maybe wikipedia should describe that ^ is common representation among first lines, not in details section. Also macOS (former osx) uses this symbol everywhere: http://www.macinstruct.com/images/command.png
Yes, but it is so annoying and confusing that these symbols are not printed on the actual keyboard. Looking at the keyboard doesn't help much when I try to press a shortcut I just saw in the menu.
And then imagine trying to escape telnet on an international keyboard (Swedish in my case). Telnet actually kind of works, if you press ctrl+altgr+8 (which is one hell of a hand-twister), but many games and GUIs ONLY allow you to press the listed, with no other modifiers.
So many games don't even allow you to open the console, because they assume that your key next to 1 is ~, and so don't work for § (next to 1) or altgr+¨ (the layout's ~). Or switch between looking at characters or scancodes depending on the context, and thus work in some cases but not all.
^D, Ctrl+D and C-d are all different ways of saying the same thing. There's nothing particularly neutral about Ctrl+D, any more than there is about using the word 'water' to mean the substance of which the oceans are mostly comprised — it's just another dialect's term.
The same argument you made could be used if the author used the unicode codes for Ctrl+D, which I find to be an indication that the argument was a bit weak. The article itself is written in English, and to expand upon your metaphor, tt would be strange to use the term agua to refer to water in an English article. Language is really based around what people use, so using what people know is generally considered good communication. If you use something different it's considered good form to explain why. Each representation you chose is effectively shorthand for the English phrase 'Control + D', just with different stylistic representations. People are much more familiar with Ctrl+D to refer to the key combination of Control and D.
Anyways, I had the same issue when I first started using Linux. It probably took me over a year to realize the caret stood for ctrl, and that's only because I accidentally typed it in something that printed the codes literally.
It's not about neutrality, it's about ease of understanding. For me at least, when speaking about something that can be entered into a keyboard ^D is less obvious than Ctrl+D–I need to press the key labeled "control" to issue the proper command, the key labeled "^" will not suffice.
To be really pedantic (sorry! I'm not complaining about your comment), your keyboard does not have any key labelled 'control', it is always (AFAIK) abbreviated as 'ctrl'. Which is really weird to me, as it's hardly a big word needing abbreviating, and keyboards often have other long words written on the keys ('delete', 'page down', and so on).
On top of that, the shortened 'ctrl' is really a terrible abbreviation. It's not obvious that it stands for 'control' and I would guess that most non-techy people would have no idea that it means this word. Plus, it's near to another key with multiple letters ('alt'). The overall effect is that 'ctrl' appears to just be a jumble of letters with some esoteric meaning. A really odd design decision. Why not just put 'control' on the key and be done with it?
You're incorrect, especially for the typical reader here. A good chunk (maybe not over 50%, but its gotta be close) of the regular readers on this site use Macs. Most Mac keyboards, including the ones on the Macbook Pro, spell it out. Same for most non IBM/IBM-PC compatible keyboards.
How odd! My mac keyboard is a similar design, but has 'ctrl', and has no writing on the shift keys, caps lock and so on. The only unabbreviated word it has is 'delete'.
Perhaps the standard is something to do with the country (mine is a UK layout).
Also ^| (as in, "control pipe") which is a synonym for ^\. At least for me, | is faster to hit than \
And since we're on this topic: if I write a for loop in bash that runs a slow command 1000 times (ImageMagick comes to mind), and I realise something has gone wrong, is there an easy way of breaking the outer loop?
IIRC, on Unix, Ctrl-\ sends the quit signal, which causes the process receiving it to do a core dump (before exiting), which can be used for post-mortem debugging, whereas Ctrl-C sends the kill signal, which makes the process terminate without any core dump. Those are the default actions for the signals.
Neat. So when my terminal is spewing output because I ran "cat massivefile" instead of "cat massivefile | head", I can hit ctrl-D to stop it instead of repeatedly hitting ctrl-C and despairing.
eof VEOF EOF character
eol VEOL EOL character
eol2 VEOL2 EOL2 character
erase VERASE ERASE character
erase2 VERASE2 ERASE2 character
werase VWERASE WERASE character
intr VINTR INTR character
kill VKILL KILL character
quit VQUIT QUIT character
susp VSUSP SUSP character
start VSTART START character
stop VSTOP STOP character
dsusp VDSUSP DSUSP character
lnext VLNEXT LNEXT character
reprint VREPRINT REPRINT character
status VSTATUS STATUS character
Back in the day, using a slow modem or teletype, discard (flush output) was super important, but several years back when I hooked up an actual Wyse dumb terminal to a Linux box I was dismayed to discover that it's actually not implemented in Linux.
Nice. Reminds me of using the "stty -a" and "stty <some_param>" commands many times on Unix terminals, back in the day, for some of those settings you list, also for things like CR/LF translation (ocrnl, onlcr, ...), raw, sane, ...
Also, a side note, I would rather just run "head massivefile" or even better "less massivefile" (because, most probably I'd want to see past what head shows by default). Running cat and then piping it to another program is inefficient, 2 forks + pipe.
If memory serves well, there was also the amazing Ctrl-O, which allowed you to send control sequences over a busy terminal --for example when scrolling a lot of text, seems to be mapped to the arcane VDISCARD and unsupported by Posix & Linux.
An important upshot is that TTY I/O never actually ends; EOF from a TTY is a temporary condition, and input can continue.
In the C standard library, you just clearerr(stdin) and keep reading.
If a program takes two files as input and obeys the - convention for specifying stdin (or has some other way of opening the tty more than once), you can do:
$ program - -
then give it two inputs, each followed by [Ctrl-D][Enter]. For instance "cat - -".
This sort of thing subtly breaks with some utilities. Try coaxing GNU diff to compare two pieces of tty input, haha.
You can work around this with other shell trickery. This might work in your shell:
$ program <(cat) <(cat)
The program itself isn't involved in opening the TTY / reading from it, etc, that is all handled by your shell before fork/execing program. program doesn't know that any of these shenanigans have happened.
It probably uses more memory (the shell has to have both stdin's in memory before it can exec the program), but overall I have mostly abandoned trying to use '-' as an input because of the way some tools, perhaps less-steeped in unix-y traditions, don't honor it correctly.
On Linux, you can compile in kernel support for a "Magic SysRq" key which causes SysRq to give you a menu of various debug printing and other actions. It works on serial consoles also, where instead of SysRq, a serial line break signal can map to the action (so it is completely out-of-band relative to serial data).
It generates SIGINFO on BSD. Which is even more useful and lets long running programs display progress of their choosing. E.g. how far has this big file copy come along?
On Linux, some programs (e.g. dd) actually do the same in SIGUSR1. I don't think it's possible to bind a key to sending USR1 so if you start a long dd you have to run the kill1 -USR from another shell. Or an awkward ^Z, then`kill -USR1 $(jobs -p)` then `fg`.