Perché questo comando 'at' non stampa sull'output standard?


15

Sono un novizio Linux relativo. Sto cercando di imparare come utilizzare in atmodo da poter pianificare le attività da iniziare in un secondo momento, senza utilizzare sleep. Ho esaminato questa domanda precedente per chiedere aiuto.

La mia domanda è, nel seguente script bash di esempio che ho creato, perché "Running" non viene mai - per quanto posso dire - stampato sull'output standard (cioè la mia console bash)?

#!/bin/bash

echo "Started"

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

echo "Finished"

L'unico output che vedo è, ad esempio:

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

La risposta alla mia domanda si trova nell'avvertimento? In tal caso, in cosa /bin/shdifferisce dallo standard output?


prova questo:sleep 3m; echo Running
Jasen,

Risposte:


18

Perché atnon esegue i comandi nel contesto della sessione dell'utente connesso. L'idea è che è possibile pianificare l'esecuzione di un comando in un momento arbitrario, quindi disconnettersi e il sistema si occuperà di eseguire il comando all'ora specificata.

Si noti che la pagina di manuale at(1)specifica (la mia enfasi):

All'utente verranno inviati messaggi di errore standard e output standard dai suoi comandi, se presenti. La posta verrà inviata usando il comando / usr / sbin / sendmail.

Quindi dovresti controllare il tuo spool di posta locale o, in caso contrario, i registri di posta del sistema locale. / var / spool / mail / $ USER è probabilmente un buon punto di partenza.

Si noti inoltre che "Iniziato" e "Finito" provengono dalla sceneggiatura esterna e di per sé non hanno nulla a che fare con at. Potresti eliminarli o atinvocare e otterrai essenzialmente lo stesso risultato.


8

Come ha spiegato @ MichaelKjörling, qualsiasi output prodotto dal tuo atlavoro verrà acquisito e inviato tramite e-mail. Se non hai un MTA - Mail Transfer Agent in esecuzione nella tua scatola, l'e-mail potrebbe essere in un limbo e non saprai nemmeno che atsta tentando di farlo.

Un MTA, è un programma come sendmailo postfixche può "consegnare" e-mail a una destinazione appropriata. In questo caso lo consegnerà a una coda di posta (un file nella directory /var/spool/mail) sul tuo sistema locale. Ogni utente sul sistema può avere una coda in questa directory.

Sul mio sistema Fedora, se avvio, sendmailpuò verificarsi la consegna della posta locale. Di solito ce l'ho.

$ sudo service start sendmail

Ora possiamo vedere che la mia coda di posta per il mio account utente samlè vuota:

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

Quindi ora eseguiamo il atlavoro:

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

Possiamo vedere che il lavoro è in attesa di essere eseguito con atq:

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

Eseguendolo di nuovo dopo un paio di minuti possiamo vedere che il atlavoro è completo:

$ atq
$

Per inciso, con il mio MTA in esecuzione ora ricevo questo messaggio nel mio terminale:

Hai nuovi messaggi in / var / spool / mail / saml

Quindi controlliamo:

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

Sì, abbiamo posta, quindi diamo un'occhiata usando mutt:

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

Abbiamo questo nella "posta in arrivo" della nostra coda di posta:

     ss di posta in arrivo di mutt

Diamo un'occhiata a questa email:

     msg di mutt

E ha funzionato.


@ MichaelKjörling - mutt rulz Cool
slm

5

Sto eseguendo Debian 8.1 (jessie)
Puoi avere l'output 'at' su un terminale 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>

Un minuto dopo, e 'ZZZZZ' apparirà nel tuo terminale ...


2

Le risposte sopra sono il modo standard / "giusto" per farlo.

Un altro approccio più semplice da un punto di vista più "dell'utente finale" è quello di fare in modo che qualsiasi attività pianificata o in background scriva il proprio output in un file "log". Il file può trovarsi ovunque sul tuo sistema, ma se l'attività è in esecuzione come root (da cron, ecc.), Allora da qualche parte sotto /var/logè un buon posto per metterlo.

Ho creato la /var/log/maintdirectory e l'ho resa leggibile da tutti e ho un file leggibile sotto quello chiamato "backup" dove registro l'output dai miei script di backup.

Ho creato la mia directory in modo che i miei file non si confondano con le cose generate dal sistema.

Per mettere roba lì (in bash):

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

Ciò >>provoca l'aggiunta dei messaggi al file invece di sovrascriverlo ogni volta.

Se il mio script ha un sacco di output, io uso uno script o una funzione per l'output, quindi tutto viene fatto allo stesso modo. Di seguito è la mia attuale (versione overkill): (le cose VERBOSE sono lì per quando sto eseguendo lo script da un terminale e voglio vedere cosa sta succedendo per scopi di debug.)

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

Modifica: atesempio semplicistico che scrive in un file utente

Non l'ho usato per sempre, quindi l'ho capito con un paio di semplici script.

Il primo script pianifica semplicemente l'evento utilizzando at. Il comando stesso potrebbe essere semplicemente digitato in un terminale, ma io sono pigro, specialmente quando devo farlo più volte mentre lo collaudo senza ingannare con la cronologia dei comandi.

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

Il secondo script è quello programmato per l'esecuzione

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

Ho creato entrambi gli script in un editor di testo, li ho salvati e poi li ho resi ciascuno eseguibile usando chmod 700 script-file-name. Li ho messi entrambi nella mia $HOME/bindirectory per comodità, ma potrebbero essere ovunque il mio utente abbia pieno accesso. Uso 700per qualsiasi script che è solo per il test, ma su un singolo sistema utente, potrebbe anche essere 755.

Ho già una directory chiamata /home/bigbird/logper salvare l'output da mytest_at_script. Questo può anche essere ovunque l'utente abbia pieno accesso. Assicurati solo che esista prima che lo script venga eseguito o chiedi allo script di crearlo.

Per eseguirlo, mi sono appena assicurato che il tempo per il atcomando mytest_at_runfosse un po 'in futuro e poi l'ho eseguito da un terminale. Ho quindi atteso che funzionasse ed esaminassi il contenuto di $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$

Alcune note:

Anche se sto correndo atdal mio utente, non conosce il mio ambiente come la mia PATHe la mia directory home, quindi non lo presumo. Uso percorsi completi come farei per qualsiasi cronlavoro. E se mai volessi farlo diventare un cronlavoro, non dovrò cambiare nulla solo per farlo funzionare.

Ho usato >>a mytest_at_scriptemettere accodamento al file di log invece >che avrebbe sostituito in ogni corsa. Utilizzare quello che meglio si adatta alla propria applicazione.


mi potete fornire qualche esempio per scrivere l'output nel file di log usando il comando AT, sto provando nel modo seguente ma nessun risultato, ora + 1 min a> echo "" ciao ">> / home / camsarch / cams_scripts / texsttest. txt at> <EOT>
Pavan Kumar Varma

@PavanKumarVarma: aggiunto un esempio semplicistico (testato) che utilizza atper scrivere su un file. Sembra che tu abbia la sequenza di chiamate al contrario nel tuo esempio. Non sono molto bravo a dire atquando eseguire il lavoro, quindi ho appena programmato un tempo nel prossimo futuro.
Joe,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.