at some time from now do something (and maybe also show result in console)
The correct at usage is at <timespec>
, where <timespec>
is the time specification. You can also use the -f
option to specify the file containing the commands to execute. If -f
and no redirection is used, at will read the commands to execute from the stdin (standard input).
In your example, to execute "some command" (I chose "some command" to be "echo hi" in the example below) one minute right after you hit enter (now), the intended <timespec>
to be used is now + 1 minute
. So, in order to obtain the result you want with a one-liner solution, please use the command below:
echo 'echo hi' | at now + 1 minute
This is supposed (and will do) to run the echo hi
command after one minute. The problem here is that the echo hi
command will be executed by the at command in a dummy tty and the output will be sent to the user's mail box (if it is correctly configured - which requires a more extensive explanation on how to configure a mail box in a unix machine and is not part of the scope of this question). The bottomline is that you won't be able to directly see the result of echo hi
in the same terminal you issued the command. The easiest alternative is you redirect it to "some file", for example:
echo 'echo hi > /tmp/at.out' | at now + 1 minute
In the above example, "some file" is /tmp/at.out
and the expected result is that the file at.out
under /tmp is created after one minute and contais the text 'hi'.
In addition to the now + 1 minute
example above, many other time specifications can be used, even some complex ones. The at command is smart enough to interpret pretty human readable ones like the examples below:
now + 1 day
, 13:25
, mid‐night
, noon
, ...
Please refer to at's man page for more about the possible time specifications as the possible variations are pretty extensive and may include dates, relative or absolute times, etc..
Run the sleep
in a subshell:
(sleep 60; echo -e '\nhi') &
Note: on Linux you can give the argument to sleep in seconds or with a suffix s/m/h/d (for seconds, minutes, hours, days). On BSD the argument has to be in seconds
The "hi" stream is printed in my prompt (in the
stdin
) and not in mystdout
No, it's not "printed in your stdin
".
If you pressed return, it wouldn't try to run hi
as a command. It's just that the backgrounded echo
printed hi
while the cursor was after your prompt.
Perhaps you want to print a leading newline, like (sleep 1m && echo -e '\nhi' &)
. (Adjust as necessary for the echo
in your shell. Or use printf
for portability.)
I put the &
inside the subshell to "disown" the background job, so you also avoid the "noise" of [1]+ Done
. With &&
between the commands, &
applies to the whole compound-command chain, so it returns to the shell prompt right away instead of waiting for sleep
to exit like you'd get with (sleep 1; echo ... &)
Here's what happens (with 1 second delay):
peter@volta:~$ (sleep 1 && echo -e '\nhi' &)
peter@volta:~$
hi
# cursor is at the start of this empty line.
Bash doesn't know that echo
printed something, so it doesn't know it needs to re-print its prompt or clean up the screen. You can do that manually with control-L
.
You could write a shell function that gets bash to re-print its prompt after echo
finishes. Just doing echo "$PS1"
won't reproduce any already-typed characters. kill -WINCH $$
on my system gets bash to re-print its prompt line without clearing the screen, leaving hi
on a line by itself before the prompt. SIGWINCH is sent automatically when the WINdow size CHanges, and bash's response to it happens to do what we want.
It might work with other shells, but I'm not attempting to make this 100% portable / POSIX. (Unfortunately, this only works on bash4.4, not bash4.3, or depends on some setting I'm unaware of)
# bash4.4
peter@volta:~$ (sleep 2 && echo -e '\nhi' && kill -WINCH $$ &)
peter@volta:~$ ljlksjksajflasdf dfas # typed in 2 seconds
hi
peter@volta:~$ ljlksjksajflasdf dfas # reprinted by Bash because of `kill -WINCH`
You could easily wrap this up in a shell function that takes a sleep arg and a message.
bash 4.3 doesn't re-print its prompt after SIGWINCH, so this doesn't work there. I have shopt -s checkwinsize
enabled on both systems, but it only works on the Bash 4.4 system (Arch Linux).
If it doesn't work, you could try (sleep 2 && echo -e '\nhi' && echo "$PS1" &)
, which "works" if the command line is empty. (It also ignores the possibility that PROMPT_COMMAND
is set.)
There's no really clean way to get terminal output to mix with whatever you might be doing on your terminal later, when the timer fires. If you're in the middle of scrolling something in less
, you could easily miss it.
If you're looking for something with interactive results, I suggest playing an audio file. e.g. with a command-line player like mpv
(nice fork of MPlayer2). Or pick a video file so a new window opens.
(sleep 1 && mpv /f/share/music/.../foo.ogg </dev/null &>/dev/null &)
You might want to have your echo
open a new xterm / konsole / gnome-terminal. Use an option that keeps the terminal open after the command exits.