언젠가는 무언가를 해보십시오 (그리고 콘솔에 결과를 표시 할 수도 있습니다)


12

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 Corde의 답변으로 나는 시도했다.

(sleep 2 && echo -e '\nhi' && kill -WINCH $$ &)

이것은 Bash 4.4에서는 제대로 작동하지만 일부 이전 버전에서는 보이지 않습니다 (답변의 주석 참조). 나는 개인적으로 내 환경에서 Bash 4.3을 사용합니다.


2
킬 플래그가 GNU 스타일이었고 재배치하여 "원더 죽이기"처럼 들리지 않기를 바랍니다!
NH.

답변:


6

"hi"스트림은 내 프롬프트가 stdin아닌 프롬프트에 인쇄 됩니다.stdout

아니요, "인쇄"로 인쇄 되지 않았습니다stdin .

return 키를 누르면 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.

bash echo가 끝나면 프롬프트를 다시 인쇄하도록 쉘 함수를 작성할 수 있습니다. 그냥 일을 echo "$PS1"어떤 이미 입력 된 문자를 재현하지 않습니다. kill -WINCH $$내 시스템에서 화면을 지우지 않고 프롬프트 행을 다시 인쇄하도록 프롬프트를 다시 인쇄하기 위해 bash를 얻습니다 hi. WINdow 크기가 변경되면 SIGWINCH가 자동으로 전송되고 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두 시스템에서 사용할 수 있지만, 그것은 단지 배쉬 4.4 시스템 (아치 리눅스)에서 작동합니다.

작동하지 않으면 (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을 열 수도 있습니다 . 명령이 종료 된 후 터미널을 열린 상태로 유지하는 옵션을 사용하십시오.


정말 고마워 데이빗, 나는 엄지 손가락. 이것은 내가 찾은 것에 관해 내가 가장 가까운 것입니다. Enter에코가 나타난 직후에 키 누름 이벤트 를 에뮬레이트하도록 다음 명령을 업그레이드하는 방법이 있습니까? 그래서 자동으로 콘솔의 기본 프롬프트 로 돌아갑니다 . (sleep 2 && echo -e '\nhi' && kill -WINCH $$ &).
Arcticooling

@Arcticooling 것은 : kill -WINCH $$ 않는 터미널에서 실행중인 쉘의 프롬프트를 새로 고칩니다. 그것은 그것을 사용하는 전체 요점이었습니다. Enter 키를 누르면 부분적으로 입력 된 명령이 제출되지만 WINCH는 표시하지 않습니다. 아무 것도 입력하지 않으면 빈 프롬프트가 나타납니다.
Peter Cordes

1
을 입력하기 시작했다면 rm -rf ~/some/directory잘못된 시간에 Enter가 실행되었을 가능성이 있습니다 rm -rf ~/. (안전 팁 : 경로 입력을 마친 control-a를 변경하고로 변경 ls하면 rm -rf언제든 뚱뚱한 손가락으로 들어가도 하루를 망치지 않습니다.)
Peter Cordes

유선, 나는 실행 (sleep 2 && echo -e '\nhi' && kill -WINCH $$ &)하고 메아리가 나타난 후에 나는 빈 프롬프트를 보았습니다. 타격 후에 만 Enter기본 프롬프트로 돌아 왔습니다 ... 오해하면 죄송합니다. Bash를 처음 사용합니다.
Arcticooling

@ Arcticooling : Konsole 터미널 에뮬레이터에서 Arch Linux의 Bash 4.4를 사용하고 있습니다. 나는 내 명령이 적어도 다른 버전의 bash에 이식 가능하기를 바랬지 만 어쩌면 그렇지 않을 수도 screen있습니다.
Peter Cordes

13

올바른의 사용법은 at <timespec>여기서 <timespec>시간 사양입니다. 이 -f옵션을 사용하여 실행할 명령이 포함 된 파일을 지정할 수도 있습니다 . -f리디렉션이 사용되지 않으면 at은 표준 입력 (표준 입력)에서 실행할 명령을 읽습니다.

귀하의 예에서, "some command"(아래 예에서는 "some command"를 "echo hi"로 선택)를 실행하려면 enter (지금)를 누른 직후 1 분이 <timespec>됩니다 now + 1 minute. 따라서 원 라이너 솔루션으로 원하는 결과를 얻으려면 아래 명령을 사용하십시오.

echo 'echo hi' | at now + 1 minute

이것은 echo hi1 분 후에 명령 을 실행하는 것으로 간주됩니다 . 여기서 문제 echo hi는 더미 tty의 at 명령에 의해 명령이 실행되고 출력이 사용자의 메일 박스로 전송된다는 것입니다 (올바르게 구성된 경우-메일 박스를 구성하는 방법에 대한 자세한 설명이 필요함) 유닉스 머신 이며이 질문의 범위에 속하지 않습니다). 결론 echo hi은 명령을 실행 한 동일한 터미널에서 결과를 직접 볼 수 없다는 것 입니다. 가장 쉬운 대안은 다음과 같이 "일부 파일"로 리디렉션하는 것입니다.

echo 'echo hi > /tmp/at.out' | at now + 1 minute

위의 예에서 "일부 파일"은 /tmp/at.out예상 결과는 at.out/ tmp 아래 의 파일 이 1 분 후에 생성되고 텍스트 'hi'를 포함합니다.

now + 1 minute위 의 예 외에도 다른 많은 시간 사양을 사용할 수 있으며 일부 복잡한 사양도 사용할 수 있습니다. at 명령은 아래 예제와 같이 사람이 읽을 수있는 것들을 해석하기에 충분히 영리합니다.

now + 1 day, 13:25, mid‐night, noon, ...

가능한 변동은 매우 광범위하며 날짜, 상대 또는 절대 시간 등을 포함 할 수 있으므로 가능한 시간 사양에 대한 자세한 내용은 맨 페이지를 참조하십시오.


2
at기본적으로 메일을 통해 출력을 보내지 만 제대로 작동하려면 올바르게 구성해야합니다.
Simon Richter

이제 답변에 100 회 현상금을 제공합니다. 아래의 현상금 메시지를 읽고 at <timespec>사용하고있는 플래그와 사용중인 플래그 및 Ubuntu 16.04 xenial에 적합한 지 더 자세히 설명하도록 편집 하십시오.
Arcticooling

좋아, 나는 대답의 세부 수준을 높여서 지금보다 교훈적이되었습니다. 일부 사람들에게는 약간 긴 소리가 들릴지 모르지만, 작동하는 예제와 작동 방식을 명확하게 인용하므로 의심의 여지가 없습니다.
Marcelo

7

sleep서브 쉘에서 다음을 실행하십시오 .

(sleep 60; echo -e '\nhi')  &

참고 : Linux에서는 인수를 잠자 게하거나 접미사 s / m / h / d (초, 분, 시간, 일)를 지정할 수 있습니다. BSD에서 인수는 초 단위 여야합니다.


나는이 방법으로 작은 문제가 ---은 "안녕하세요"스트림 내 프롬프트에 인쇄합니다 (에 stdin)이 아니라 내에서 stdout(정기적으로이하는 것처럼 echo).
Arcticooling

1
터미널의 출력이 프롬프트와 다른 명령의 출력과
섞이지 않게하려면

이 리디렉션은 @PiedPiper에 실패했습니다 (sleep 10s; echo 'hi') & 1>. 나는 지금 이것에 대해 더 많이 읽습니다.
Arcticooling

2
문서를 읽는 것은 항상 좋은 생각입니다 :)
PiedPiper

1
@Arcticooling stdinand 의 의미가 혼동 된 것 같습니다 stdout. 터미널에서 물건이 나타나는 위치와 관련이 없습니다. 대신 특정 프로세스 (기본적으로 프로그램) 와 관련하여 해석해야합니다 . 프로세스의 표준 입력 ( "stdin")은 프로세스가 데이터를 읽을 수있는 소스이며 프로세스의 표준 출력 ( "stdout")은 데이터를 쓸 수있는 대상입니다. 이러한 소스와 대상은 다른 프로그램이나 파일 또는 터미널 자체 일 수 있습니다 (입력 한 내용이 stdin으로 이동하고 stdout에 오는 모든 것이 표시됩니다).
David Z

3

그것은 당신의 출력 파이프 있기 때문에 실패 echo "hi"그냥, hi로를 at, 그러나 at그것의 입력이 기본 시스템 쉘 (일반적으로 bash는 있지만 시스템에 따라 때로는 뭔가 다른)에 의해 수행 될 수 있음을 예상하고있다.

이:

at 1m << EOF
echo "hi"
EOF

당신이하려고하는 것처럼 보입니다. 일반적으로 이러한 유형의 작업을 수행하는 데 사용되는 '여기 문서'라는 셸 구성을 사용합니다 ( echo명령을 사용하는 것보다 여러 줄을 더 잘 처리 하고 필요에 따라 새 파일을 만들 필요가 없기 때문에) cat)를 사용하여 echo다음을 사용하여 다소 복잡한 것으로 변환합니다 .

echo 'echo "hi"' | at 1m

그것은 그 지적 아마 가치가 at호출 된 사용자에게 모든 명령 출력 우편으로 보내드립니다 at명령을 사용하여 지연으로 대신 터미널에 출력을 찾아야의 명령을 sleep것 서브 쉘에서. 특히, 이것은 시스템의 사용자 정의를 수행하지 않았거나 로컬 메일 스풀을 읽으려는 경우를 통해 명령의 출력을 얻을 수 없음을 의미합니다 at.


어떤 이유로 든 두 예제 모두 오류가 발생했습니다 syntax error. Last token seen: m Garbled time . 왜 그런지 모르겠습니다. 우분투 16.04, Bash 4.0을 사용합니다. 다른 시스템에서 그렇게했을 수도 있습니다. at추가 인수없이 입력해도 여전히 같은 오류가 발생합니다. 여기에 더 많은 데이터가 있습니다 .
Arcticooling

1
at 1mposix 호환에는 작동하지 않습니다 at. 이 명령은 할 필요가있을 것이다at now + 1 minute
PiedPiper

@PiedPiper는 정확하고 1m은 POSIX 호환 버전과 호환되지 않습니다. at단, 구문을 수락하는 버전이 있다고 가정했습니다.
Austin Hemmelgarn

@PiedPiper at 1m는 POSIX가 아니지만 POSIX 호환 구현은 at원하는대로 해석 할 수 있으며, 한 달 전에 오류를 반환하거나 의미 at를 해석하는 것과 같은 의미로 해석하기에 적합 하지 않습니다 . IOW, POSIX가 아닌 코드입니다. now + 1 minuteat 1m
Stéphane Chazelas

2

@Peter Cordes의 답변과이 답변 /programming/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;
}

그런 다음 아래 명령을 실행하십시오. (나는 dir / tmp /에 a.out을 넣었다.

(sleep 2 && echo -e '\nhi' && /tmp/a.out &)

또는

(sleep 2 && echo -e '\nhi' && /tmp/a.out /proc/$$/fd/0 &)

BTW kill -WINCH $$는 젠투에서 Bash 4.3과 함께 잘 작동합니다.


1

위의 답변을 바탕으로 다음과 같이 내장 명령으로 출력을 터미널로 보낼 수 있습니다.

echo "echo hi >$(tty); kill -WINCH $$" | at now + 1 minute

tty명령은 현재 터미널의 장치 경로를 반환하여 $(...)bash가 하위 셸에서 해당 장치를 실행하도록하고, kill 명령은 현재 프로세스에 bash가 $ PS1 프롬프트를 다시 인쇄하도록하는 신호를 보냅니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.