이 "at" 명령이 표준 출력으로 인쇄되지 않는 이유는 무엇입니까?

이 "at" 명령이 표준 출력으로 인쇄되지 않는 이유는 무엇입니까?

저는 Linux에 상대적으로 초보자입니다. at을 사용하지 않고 나중에 작업을 시작하도록 예약할 수 있도록 사용 방법을 배우려고 합니다 sleep.이전 질문도움을 요청.

내 질문은 내가 만든 다음 예제 bash 스크립트에서 왜"달리기"내가 아는 한, stdout(예: bash 콘솔)으로 인쇄할 수는 없습니다.

#!/bin/bash

echo "Started"

at now + 1 minutes <<EOF
echo "Running"
EOF

echo "Finished"

내가 보는 유일한 출력은 예를 들어 다음과 같습니다.

Started
warning: commands will be executed using /bin/sh
job 3 at Fri Jul 12 17:31:00 2013
Finished

내 질문에 대한 답을 경고에서 찾을 수 있나요? 그렇다면 /bin/sh표준 출력과 어떻게 다릅니까?

답변1

at로그인한 사용자 세션의 컨텍스트에서는 명령이 실행되지 않기 때문입니다 . 아이디어는 언제든지 명령이 실행되도록 예약한 다음 로그아웃하면 시스템이 지정된 시간에 명령 실행을 처리한다는 것입니다.

매뉴얼 페이지에는 다음과 같이 at(1)구체적으로 명시되어 있습니다(필자의 강조).

사용자에게 메일이 발송됩니다.명령의 표준 오류 및 표준 출력(사용 가능한 경우) 메일은 /usr/sbin/sendmail 명령을 사용하여 전송됩니다.

따라서 로컬 메일 풀을 확인해야 하며, 실패할 경우 로컬 시스템 메일 로그를 확인해야 합니다. /var/spool/mail/$USER는 시작하기에 좋은 곳일 수 있습니다.

at또한 "시작"과 "완료"는 외부 스크립트에서 파생되며 그 자체로는 전혀 관련이 없습니다. 꺼내거나 at전화하면 본질적으로 동일한 결과를 얻을 수 있습니다.

답변2

저는 Debian 8.1을 실행하고 있습니다(jessie).
tty를 사용하여 "at" 출력을 터미널로 가져올 수 있습니다.

$ tty
/dev/pts/1

$ at now + 1 min
warning: commands will be executed using /bin/sh
at> echo 'ZZZZZ' > /dev/pts/1
at> <EOT>

잠시 후 터미널에 "ZZZZZ"가 나타날 것입니다...

답변3

@MichaelKjörling이 설명하듯이, 귀하의 작업으로 생성된 모든 결과물은 at캡처되어 귀하에게 이메일로 전송됩니다. 당신이 달리고 있지 않다면MTA - 메일 전송 에이전트at이메일이 편지함에 표시되면 이메일이 정체되어 이메일이 이 작업을 시도하고 있다는 사실조차 알지 못할 가능성이 있습니다 .

sendmailMTA는 또는 postfix이메일을 적절한 대상으로 "라우팅"할 수 있는 프로그램입니다 . 이 경우 /var/spool/mail로컬 시스템의 메일 대기열(디렉토리 아래 파일)로 전달됩니다. 시스템의 각 사용자는 이 디렉터리에 대기열을 가질 수 있습니다.

내 Fedora 시스템에서 부팅하면 sendmail로컬 메일 배달을 받습니다. 하지만 저는 보통 꺼두곤 합니다.

$ sudo service start sendmail

이제 내 사용자 계정의 메일 대기열이 비어 있음을 확인할 수 있습니다 saml.

$ ll /var/spool/mail/|grep saml
-rw-rw----. 1 saml mail       0 Jul 12 19:33 saml

이제 작업을 실행합니다 at.

$ at now + 1 minutes <<EOF
echo "Running"
EOF
job 96 at Fri Jul 12 19:38:00 2013

작업이 실행 대기 중인 것을 볼 수 있습니다 atq.

$ atq
96  Fri Jul 12 19:38:00 2013 a saml

몇 분 후에 다시 실행하면 at작업이 완료된 것을 확인할 수 있습니다.

$ atq
$

그런데 이제 MTA가 실행 중일 때 터미널에 다음 메시지가 표시됩니다.

/var/spool/mail/saml에 새 메일이 있습니다.

그럼 확인해 봅시다:

$ ll /var/spool/mail/|grep saml
-rw-rw----. 1 saml mail     651 Jul 12 19:38 saml

예, 이메일을 받았습니다. 다음 명령을 사용하여 확인해 보겠습니다 mutt.

$ mutt -f /var/spool/mail/saml

메일 대기열의 "받은 편지함"에 다음이 있습니다.

     뮤트 받은편지함 ss

이 이메일을 살펴보겠습니다.

     똥개님의 SS 메시지

효과가 있었습니다.

답변4

위의 답변은 표준/"올바른" 방식입니다.

보다 "최종 사용자" 관점에서 볼 때 또 다른 간단한 접근 방식은 예약된 작업이나 백그라운드 작업이 해당 출력을 "로그" 파일에 기록하도록 하는 것입니다. 이 파일은 시스템 어디에나 위치할 수 있지만 작업이 루트(슬레이브 등 cron)로 실행되는 경우 다음 위치 중 하나에 /var/log파일을 저장하는 것이 좋습니다.

저는 /var/log/maint디렉터리를 생성하여 모든 사람이 읽을 수 있도록 만들었습니다. "backup"이라는 디렉터리 아래에 읽을 수 있는 파일이 있는데, 여기서 백업 스크립트의 출력을 기록합니다.

내 파일이 시스템 생성 콘텐츠와 섞이지 않도록 나만의 디렉터리를 만들었습니다.

거기에 물건을 넣으세요(bash에):

BACKUP="/var/log/maint/backup"
echo "my message" >> "${BACKUP}"

이렇게 하면 >>메시지가 매번 덮어쓰는 대신 파일에 추가됩니다.

출력이 많은 스크립트가 있는 경우 출력에 스크립트나 함수를 사용하여 모든 작업이 동일한 방식으로 수행됩니다. 내 현재(과도한 버전)는 다음과 같습니다. (터미널에서 스크립트를 실행하고 디버깅 목적으로 무슨 일이 일어나고 있는지 확인하려고 할 때 VERBOSE 항목이 나타납니다.)

#!/bin/bash
## backup_logger
## backup system logging module
## Copyleft 01/20/2013 JPmicrosystems
## Usage is ${SCRIPT_NAME} [-v] [<caller> <log message text>]
## If present, -v says log to console as well as to the log file
## <caller> is the name of the calling script
## If <caller> <log message text> is not present, write a blank line to the log

## Must be placed in path, like ~/bin
## If log is owned by root or another user, then this must run as root ...
## If not, it just aborts

##source "/home/bigbird/bin/bash_trace"  ## debug
SCRIPT_NAME="$(basename $0)"
USAGE="Usage is ${SCRIPT_NAME} [-v] [<caller> <log message text>]"
SYSLOGDIR='/var/log/maint'
SYSLOGFILE="${SYSLOGDIR}/backup.log"

LOGGING=1
VERBOSE=0
if [ "${1}" == "-v" ]
then
  VERBOSE=1
  shift
fi

##LOGGING=0  ## debug
##VERBOSE=1  ## debug

## Only zero or two parameters allowed - <caller> <log message text>
RC=0
if [ "$#" -eq 1 ] || [ "$#" -gt 2 ]
then
  echo "${USAGE}"
  RC=1
else
  if [ ! -w "${SYSLOGFILE}" ]
  then
    touch "${SYSLOGFILE}"
    if [ $? -ne 0 ]
    then
      echo -e "$(date) ${1} ${2}"
      echo "${SCRIPT_NAME} Can't write to log file [${SYSLOGFILE}]"
      RC=1
      exit ${RC}
    fi
  fi

  if [ -n "${1}" ]
  then
    (( LOGGING )) && echo -e "$(date) ${1} ${2}"  >> "${SYSLOGFILE}"
    (( VERBOSE )) && echo -e "$(date) ${1} ${2}"
  else
    (( LOGGING )) && echo "" >> "${SYSLOGFILE}"
    (( VERBOSE )) && echo ""
  fi
fi

exit $RC

편집: at사용자 파일에 쓰는 간단한 예

이전에는 이것을 사용한 적이 없었기 때문에 몇 가지 간단한 스크립트로 문제를 해결했습니다.

첫 번째 스크립트는 이벤트를 예약하는 데 사용됩니다 at. 명령 자체는 터미널에 직접 입력할 수 있지만 게으른 편입니다. 특히 테스트하는 동안 명령 기록을 스푸핑하지 않고 명령을 여러 번 실행해야 하는 경우에는 더욱 그렇습니다.

#!/bin/bash
## mytest_at_run
## Schedule a script to run in the immediate future
echo "/home/bigbird/bin/mytest_at_script" | at 00:56

두 번째 스크립트는 실행되도록 예약된 스크립트입니다.

#!/bin/bash
## mytest_at_script
## The script to be run later
echo "$(date) - is when this ran" >> /home/bigbird/log/at.log

텍스트 편집기에서 두 개의 스크립트를 생성하고 저장한 다음 사용했습니다 chmod 700 script-file-name. 편의상 두 스크립트를 모두 내 $HOME/bin디렉토리에 배치했지만 사용자가 전체 액세스 권한이 있는 모든 위치에 있을 수 있습니다. 테스트용으로 아무 스크립트나 사용 700하지만 단일 사용자 시스템에서는 755.

/home/bigbird/log출력이 저장되는 디렉토리가 이미 있습니다 mytest_at_script. 이는 사용자가 전체 액세스 권한을 갖는 어느 곳이든 가능합니다. 스크립트가 실행되기 전에 존재하는지 확인하거나 스크립트가 생성하도록 하세요.

이를 실행하기 위해 명령의 시간 이 미래 at인지 확인한 다음 터미널에서 실행했습니다. mytest_at_run그런 다음 실행될 때까지 기다렸다가 확인합니다 $HOME/log/at.log.

bigbird@sananda:~/bin$ cat ~/log/at.log
Fri Sep 14 00:52:18 EDT 2018 - is when this ran
Fri Sep 14 00:56:00 EDT 2018 - is when this ran
bigbird@sananda:~/bin$

몇 가지 참고사항:

내 사용자로부터 실행 하더라도 at내 디렉터리, 내 홈 디렉터리 등 내 환경을 모르기 때문에 PATH그렇게 생각하지 않습니다. 나는 cron다른 직업처럼 전체 경로를 사용합니다. 작동 하게 하려면 cron실행하기 위해 아무것도 변경할 필요가 없습니다.

나는 실행할 때마다 출력을 바꾸는 대신 로그 파일에 출력을 추가 >>하곤 했습니다 . 귀하의 애플리케이션에 가장 적합한 것을 사용하십시오.mytest_at_script>

관련 정보