34

The full portion of the Bash man page which is applicable only says:

If the operating system on which bash is running supports job control, bash contains facilities to use it. Typing the suspend character (typically ^Z, Control-Z) while a process is running causes that process to be stopped and returns control to bash. Typing the delayed suspend character (typically ^Y, Control-Y) causes the process to be stopped when it attempts to read input from the terminal, and control to be returned to bash. The user may then manipulate the state of this job, using the bg command to continue it in the background, the fg command to continue it in the foreground, or the kill command to kill it. A ^Z takes effect immediately, and has the additional side effect of causing pending output and typeahead to be discarded.

I have never used Ctrl-Y; I only just learned about it. I have done fine with Ctrl-Z (suspend) only.

I am trying to imagine what this option is for. When would it be useful?

(Note that this feature doesn't exist on all Unix variants. It's present on Solaris and OpenBSD but not on Linux or FreeBSD. The corresponding setting is stty dsusp.)

Perhaps less subjectively: Is there anything that can be accomplished with Ctrl-Y that cannot be accomplished just as easily with Ctrl-Z?

3
  • @Gilles, though FreeBSD seems to have a stty dsusp, I've not managed to make it send a SIGTSTP upon ^Y (I did on Solaris). Have you? Aug 17, 2016 at 9:53
  • It's in termios, but FreeBSD's line discipline does not do anything special in response to the character. OpenBSD's line discipline does, however.
    – JdeBP
    Jan 11, 2020 at 13:44
  • 1
    dsusp didn't make it through the FreeBSD tty layer rewrite from 2008: github.com/freebsd/freebsd/commit/cc3116a
    – user313992
    Jan 11, 2020 at 14:45

4 Answers 4

23

From the 4BSD manual for csh:

A ^Z takes effect immediately and is like an interrupt in that pending output and unread input are discarded when it is typed. There is another special key ^Y which does not generate a STOP signal until a program attempts to read(2) it. This can usefully be typed ahead when you have prepared some commands for a job which you wish to stop after it has read them.

So, the purpose is to type multiple inputs while the first one is being processed, and have the job stop after they are done.

5
  • This description is subtly different from the bash manual. "...does not generate a STOP signal until a program attempts to read it." It sounds like everything in the input stream up to the ^Y will be read successfully, and then when the ^Y is hit the process will be stopped. Am I reading this right?
    – Wildcard
    Sep 15, 2016 at 23:30
  • @Wildcard in my test on Mac OS X, the process is stopped before read() returns (but after the call to read() that would have returned the Y runs), and after it is resumed it receives the input from before ^Y. I think as this was intended to be used, though, it would be used at the start of a line, so the behavior in this case would not matter. I suspect that in the actual code, it is suspended when the ^Y would have been copied into the user process read buffer.
    – Random832
    Sep 16, 2016 at 2:41
  • I was right, in the original BSD kernel's ttread function you can see this, and modern OSX
    – Random832
    Sep 16, 2016 at 3:02
  • But, when the process is resumed, the call will succeed and will contain the data you typed into your terminal before ^Y, even if you have disowned the process and closed your terminal before the process is resumed. Right? ("...after it is resumed it receives the input from before ^Y." That's what I meant; I don't usually deal in C code.) :)
    – Wildcard
    Sep 16, 2016 at 3:34
  • Yes. And it returns without a newline at the end, which is unusual for a read in canonical mode [similar to if you'd typed some text and then pressed ^D once] I suspect they didn't think about this case very much, since it's really intended to be typed at the start of a line.
    – Random832
    Sep 16, 2016 at 3:37
13

Say there's a loop reading input and executing. It may be useful to let the task finish the current instruction it computes, without interrupting it before it gets back to the command line for a new one. So thus to end a cycle. This ends the loop gracefully and prevents it from running again if read is under a timeout restriction.

7
  • But if it's going to try to read input from the terminal anyway, it will stop at that point (and wait for your input), and you can ^Z it then.
    – Wildcard
    Aug 16, 2016 at 3:07
  • Yes. See update.
    – user147505
    Aug 16, 2016 at 3:10
  • Check one more. @Wildcard
    – user147505
    Aug 16, 2016 at 3:26
  • 1
    But if it's got a timeout, wouldn't it also just end gracefully if you did nothing special? Aug 16, 2016 at 16:59
  • 1
    It might. But it might also go on and do some default job.
    – user147505
    Aug 16, 2016 at 17:04
4

I can think of one scenario where it might be useful, but it's something of a contrived edge-case.

Suppose you're debugging a script that is writing temporary files that you wish to analyze before they're deleted as part of a clean-up routine.

You could add a read foo somewhere after the files are written (but before the cleanup), run the script, and press Ctrl-Y as they're being generated. You will then be dropped to a prompt with the script suspended in the background to do whatever you need to do, and can then fg to allow the script to complete.

1
  • 1
    Seems unlikely, because the script will wait for input anyway. So you could just as easily watch for it to prompt you for input and then suspend it with ^Z. In other words: after you type fg you will have to give the script some input anyway before it will continue. Hence my question; I still don't see the point of ^Y. (Thanks for answering, though!) :)
    – Wildcard
    Aug 16, 2016 at 2:51
2

The only scenario I can think of (and even I don't find it very convincing), is if you want to use some type-ahead for a shell command. Say some command is running which will read input some time in the future. Then you can ^Y it, and then immediately type the next shell command that you want to have executed when the running command suspends. I don't think I have ever really used this in several decades of using BSD Unix.

You must log in to answer this question.

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