Por que esse comando 'at' não é impresso na saída padrão?

15

Eu sou um iniciante em Linux. Estou tentando aprender a usar atpara poder agendar tarefas para começar mais tarde, sem usar sleep. Eu estive olhando para esta pergunta anterior para obter ajuda.

Minha pergunta é, no seguinte exemplo de script do bash que eu criei, por que "Running" nunca - até onde eu sei - é impresso na saída padrão (ou seja, no meu console do bash)?

#!/bin/bash

echo "Started"

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

echo "Finished"

A única saída que vejo é, por exemplo:

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

A resposta à minha pergunta foi encontrada no aviso? Em caso afirmativo, como /bin/shdifere da saída padrão?

Andrew
fonte
tente isto:sleep 3m; echo Running
Jasen

Respostas:

18

Porque atnão executa comandos no contexto da sua sessão de usuário conectado. A idéia é que você pode agendar um comando para execução em um horário arbitrário e, em seguida, efetue logout e o sistema cuidará da execução do comando no horário especificado.

Observe que a página de manual para at(1)especificamente diz (minha ênfase):

O usuário receberá um erro padrão e uma saída padrão de seus comandos, se houver. O correio será enviado usando o comando / usr / sbin / sendmail.

Portanto, você deve verificar o spool de correio local ou, na sua falta, os logs de correio do sistema local. / var / spool / mail / $ USER é provavelmente um bom lugar para começar.

Observe também que o "Iniciado" e "Concluído" se originam do script externo e, por si só, não têm nada a ver at. Você pode retirá-los ou atinvocar e obterá basicamente o mesmo resultado.

um CVn
fonte
8

Como o @ MichaelKjörling explicou, qualquer saída produzida pelo seu attrabalho será capturada e enviada a você por e-mail. Se você não possui um MTA - Mail Transfer Agent em sua caixa, o e-mail pode estar no limbo e você nem saberá que atestá tentando fazer isso.

Um MTA é um programa como sendmailou postfixque pode "entregar" o email para um destino apropriado. Nesse caso, ele será entregue em uma fila de mensagens (um arquivo no diretório /var/spool/mail) em seu sistema local. Cada usuário no sistema pode ter uma fila neste diretório.

No meu sistema Fedora, se eu iniciar sendmail, poderá ocorrer a entrega de correio local. Eu normalmente tenho isso embora.

$ sudo service start sendmail

Agora podemos ver que minha fila de emails da minha conta de usuário samlestá vazia:

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

Então agora executamos o attrabalho:

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

Podemos ver que o trabalho está aguardando para ser executado com atq:

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

Ao executá-lo novamente após alguns minutos, podemos ver que o attrabalho está concluído:

$ atq
$

Aliás, com o meu MTA em execução, agora recebo esta mensagem no meu terminal:

Você tem novos emails em / var / spool / mail / saml

Então, vamos verificar:

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

Sim, temos e-mail, então vamos dar uma olhada usando mutt:

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

Temos isso na "caixa de entrada" da nossa fila de emails:

     ss da caixa de entrada do mutt

Vamos verificar este e-mail:

     ss da mensagem do mutt

E funcionou.

slm
fonte
@ MichaelKjörling - mutt rulz 8-)
slm
5

Estou executando o Debian 8.1 (jessie)
Você pode fazer com que a saída 'at' vá para um terminal usando tty.

$ tty
/dev/pts/1

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

Um minuto depois, e 'ZZZZZ' aparecerá no seu terminal ...

AAAfarmclub
fonte
2

As respostas acima são a maneira padrão / "correta" de fazê-lo.

Outra abordagem mais simples do ponto de vista do "usuário final" é fazer com que qualquer tarefa agendada ou em segundo plano grave sua saída em um arquivo "log". O arquivo pode estar em qualquer lugar do seu sistema, mas se a tarefa estiver sendo executada como raiz (de cron, etc.), em algum lugar abaixo /var/logé um bom lugar para colocá-lo.

Criei o /var/log/maintdiretório e o tornei legível por todos e tenho um arquivo legível sob o chamado "backup", onde registro a saída dos meus scripts de backup.

Criei meu próprio diretório para que meus arquivos não se misturassem com as coisas geradas pelo sistema.

Para colocar coisas lá (no bash):

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

O >>faz com que as mensagens sejam anexadas ao arquivo em vez de substituí-lo cada vez.

Se meu script tem muita saída, eu uso um script ou função para saída, para que tudo seja feito da mesma maneira. Abaixo está minha versão atual (exagero): (o material VERBOSE existe para quando estou executando o script em um terminal e quero ver o que está acontecendo para fins de depuração.)

#!/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

Edit: atexemplo simplista que grava em um arquivo de usuário

Não usei isso para sempre, então eu descobri isso com alguns scripts simples.

O primeiro script apenas agenda o evento usando at. O comando em si pode ser digitado em um terminal, mas sou preguiçoso - especialmente quando tenho que fazê-lo várias vezes enquanto testo sem mexer no histórico de comandos.

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

O segundo script é o que está programado para ser executado

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

Eu criei os dois scripts em um editor de texto, os salvei e os tornei cada um executável usando chmod 700 script-file-name. Coloquei os dois no meu $HOME/bindiretório por conveniência, mas eles podem estar em qualquer lugar em que meu usuário tenha acesso total. Eu uso 700para qualquer script que seja apenas para teste, mas em um sistema de usuário único, poderia ser 755.

Eu já tenho um diretório chamado /home/bigbird/logpara salvar a saída mytest_at_script. Também pode estar em qualquer lugar em que seu usuário tenha acesso total. Apenas verifique se ele existe antes da execução do script ou faça com que o script o crie.

Para executá-lo, certifiquei-me de que o tempo para o atcomando mytest_at_runfosse um pouco no futuro e, em seguida, executei-o em um terminal. Eu então esperei até ele rodar e examinei o conteúdo de $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$

Algumas notas:

Embora eu esteja fugindo atdo meu usuário, ele não conhece meu ambiente, como o meu PATHe o meu diretório pessoal, por isso não presumo isso. Eu uso caminhos completos como usaria para qualquer crontrabalho. E se eu quiser fazer um crontrabalho, não precisarei mudar nada apenas para fazê-lo funcionar.

I utilizado na saída de acréscimo para o arquivo de log em vez de que teria substituído-lo em cada corrida. Use o que melhor se adequar à sua aplicação.>>mytest_at_script>

Joe
fonte
você pode me fornecer algum exemplo para gravar a saída no arquivo de log usando o comando AT, estou tentando da seguinte maneira, mas sem resultado, agora + 1 min em> echo "" olá ">> / home / camsarch / cams_scripts / texsttest. txt em> <EOT>
Pavan Kumar Varma
@PavanKumarVarma - adicionou um exemplo simplista (testado) usando atpara gravar em um arquivo. Parece que você conseguiu a sequência de chamadas ao contrário no seu exemplo. Eu não sou muito bom em dizer atquando executar o trabalho, então apenas codifiquei um tempo em um futuro muito próximo.
Joe