저는 Ubuntu 서버 16.04를 사용하고 있으며 at
이 유틸리티를 사용하여 echo
특정 날짜와 시간을 제공하지 않고 현재 세션에서 지금부터 1분(예: 현재 시간보다 1분 앞선)에 일부 작업을 수행하려고 합니다.
실패합니다.
echo 'hi' | at 1m
at
내가 이것을 선택한 이유 sleep
는 수면이 현재 세션을 방해하므로 대부분의 시간을 사용하는 세션보다 다른 세션에서 명령을 지연시키는 데 더 적합하기 때문입니다. AFAIR는 at
그렇게 하지 않을 것이고 내 회의를 방해하지도 않을 것입니다.
업데이트_1
Pied Piper의 답변을 바탕으로 다음을 시도했습니다.
(sleep 1m; echo 'hi') &
이 접근 방식에는 문제가 있습니다. "hi" 스트림이 기본 프롬프트 내부에 인쇄되고 _
이를 포함하는 기본 프롬프트 아래에 빈 보조 프롬프트( )도 추가됩니다. 다음을 참조하세요.
USER@:~# (sleep 1m; echo 'hi') &
[1] 22731
USER@:~# hi
^C
[1]+ Done
업데이트_2
Peter Codd의 답변을 바탕으로 다음을 시도했습니다.
(sleep 2 && echo -e '\nhi' && kill -WINCH $$ &)
이것은 Bash 4.4에서는 잘 작동하지만 일부 이전 버전에서는 작동하지 않는 것 같습니다(답변의 주석 참조). 나는 개인적으로 내 환경에서 Bash 4.3을 사용합니다.
답변1
올바른 사용법은 시간 사양이 있는 at <timespec>
곳 입니다. <timespec>
또한 이 -f
옵션을 사용하여 실행할 명령이 포함된 파일을 지정할 수도 있습니다. 리디렉션이 없는 경우 -f
at은 stdin(표준 입력)에서 실행할 명령을 읽습니다.
귀하의 예에서는 Enter 키를 누른 지 1분 후에 "some command"를 실행하려면(아래 예에서는 "echo hi"로 "some command"를 선택했습니다) <timespec>
사용할 대상은 입니다 now + 1 minute
. 따라서 원하는 결과를 얻으려면 한 줄 솔루션으로 다음을 사용하십시오.
echo 'echo hi' | at now + 1 minute
그러면 echo hi
1분 후에 명령이 실행됩니다. 여기서 문제는 echo hi
명령이 가상 tty의 at 명령에 의해 실행되고 출력이 사용자의 메일함으로 전송된다는 것입니다(올바르게 구성된 경우 - UNIX 시스템에 대한 더 광범위한 설명이 필요하며 이 질문의 범위를 벗어납니다). ). 가장 중요한 점은 echo hi
명령을 실행한 동일한 터미널에서 직접 결과를 볼 수 없다는 것입니다 . 가장 간단한 대안은 다음과 같은 "일부 파일"로 리디렉션하는 것입니다.
echo 'echo hi > /tmp/at.out' | at now + 1 minute
위의 예에서 "some file"은 이고 예상되는 결과는 /tmp 아래에 1분 후에 "hi"라는 텍스트를 포함하는 /tmp/at.out
파일이 생성되는 것입니다 .at.out
now + 1 minute
위의 예 외에도 다른 많은 시간 사양, 심지어 일부 복잡한 사양도 사용할 수 있습니다. at 명령은 다음 예와 같이 사람이 읽을 수 있는 명령을 해석할 만큼 똑똑합니다.
now + 1 day
, 13:25
, mid‐night
, noon
, ...
가능한 변형은 매우 광범위하고 날짜, 상대 시간 또는 절대 시간 등을 포함할 수 있으므로 가능한 시간 지정에 대한 자세한 내용은 at의 매뉴얼 페이지를 참조하십시오.
답변2
sleep
서브셸에서 실행:
(sleep 60; echo -e '\nhi') &
참고: Linux에서는 절전 매개변수를 초 단위로 제공하거나 접미사 s/m/h/d(초, 분, 시간, 일)를 사용할 수 있습니다. BSD에서는 인수가 초 단위여야 합니다.
답변3
"hi" 스트림은 프롬프트
stdin
가 아닌 프롬프트(in) 에 인쇄됩니다.stdout
아니 그렇지아니요"당신에게 봉인되었습니다 stdin
."
Enter를 누르면 hi
명령으로 실행되지 않습니다. 커서가 프롬프트 뒤에 있을 때 echo
배경이 인쇄되는 것뿐입니다.hi
아마도 당신은 원할 것입니다선행 개행 문자 인쇄, 좋다 (sleep 1m && echo -e '\nhi' &)
. ( echo
쉘 요구 사항에 맞게 조정하거나 printf
이식성을 위해 조정하십시오.)
&
백그라운드 작업을 "거부"하기 위해 하위 쉘 안에 넣었으므로 이를 피할 수도 있습니다 [1]+ Done
. &&
명령 사이에서는 전체 복합 명령 체인에 대해 작동하므로 종료를 기다리지 &
않고 즉시 쉘 프롬프트로 돌아갑니다.sleep
(sleep 1; echo ... &)
결과는 다음과 같습니다(1초 지연).
peter@volta:~$ (sleep 1 && echo -e '\nhi' &)
peter@volta:~$
hi
# cursor is at the start of this empty line.
Bash는 무엇이 인쇄되었는지 모르기 echo
때문에 프롬프트를 다시 인쇄하거나 화면을 지워야 한다는 것을 모릅니다. 이 작업은 수동으로 수행할 수 있습니다 control-L
.
쉘 함수를 작성할 수 있습니다echo
완료되면 bash가 프롬프트를 다시 인쇄하도록 합니다.. 이렇게 하면 echo "$PS1"
이미 입력된 문자가 재현되지 않습니다. kill -WINCH $$
내 시스템에서 bash는 화면을 지우지 않고 프롬프트 줄을 다시 인쇄하고 hi
프롬프트 앞에 별도의 줄을 남겨 둡니다. SIGWINCH는 WINdow의 크기가 변경될 때 자동으로 전송되며 이에 대한 bash의 응답은 정확히 우리가 원하는 대로 수행됩니다.
다른 쉘에서도 작동할 수 있지만 100% 이식 가능/POSIX로 만들려고 노력하지는 않습니다. (불행히도 이것은 bash4.3이 아닌 bash4.4에서만 작동하거나 내가 알지 못하는 일부 설정에 따라 다릅니다.)
# 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`
수면 매개변수와 메시지를 사용하여 이를 쉘 함수로 쉽게 래핑할 수 있습니다.
bash 4.3은 SIGWINCH 후에 프롬프트를 다시 인쇄하지 않으므로 여기서는 작동하지 않습니다. 두 시스템 모두에서 활성화 했지만 shopt -s checkwinsize
Bash 4.4 시스템(Arch Linux)에서만 작동합니다.
작동하지 않으면 (sleep 2 && echo -e '\nhi' && echo "$PS1" &)
명령줄이 비어 있으면 "작동"할 수 있습니다. ( PROMPT_COMMAND
설정 가능성 도 무시합니다 .)
나중에 타이머가 실행될 때 터미널에서 수행할 수 있는 작업과 터미널 출력을 혼합하는 정말 깔끔한 방법은 없습니다. 무언가를 스크롤하는 중이라면 less
쉽게 놓칠 수 있습니다.
대화형 결과가 있는 것을 찾고 있다면 오디오 파일을 재생하는 것이 좋습니다. 예를 들어 명령줄 플레이어를 사용하면mpv
(MPlayer2의 좋은 포크). 또는 비디오 파일을 선택하여 새 창을 엽니다.
(sleep 1 && mpv /f/share/music/.../foo.ogg </dev/null &>/dev/null &)
echo
새로운 xterm/konsole/gnome-terminal을 열고 싶을 수도 있습니다 . 명령으로 종료한 후 터미널을 열어 두는 옵션입니다.
답변4
@Peter Cordes의 답변을 이 답변과 결합 https://stackoverflow.com/questions/23125527/how-to-return-to-bash-prompt-after-printing-output-from-Backgrounded-function/23125687#23125687
아래 코드는 내가 일부 변경한 후자의 답변에서 나온 것입니다. a.out 파일로 컴파일합니다(원하는 이름으로 지정).
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
char *tty = "/dev/tty";
if (argc > 1)
tty = argv[1];
int fd = open(tty, O_WRONLY);
int i;
char buf[] = "\n";
for (i = 0; i < sizeof buf - 1; i++)
if (ioctl(fd, TIOCSTI, &buf[i]))
perror("ioctl");
close(fd);
return 0;
}
그런 다음 다음 명령을 실행하십시오. (저는 a.out을 /tmp/ 디렉토리에 넣었습니다. 이를 귀하의 것으로 변경해야 할 수도 있습니다)
(sleep 2 && echo -e '\nhi' && /tmp/a.out &)
또는
(sleep 2 && echo -e '\nhi' && /tmp/a.out /proc/$$/fd/0 &)
그건 그렇고, kill -WINCH $$
나는 Gentoo에서 Bash 4.3을 사용하여 좋은 결과를 얻었습니다.