Warum wird dieser Befehl 'at' nicht in der Standardausgabe ausgegeben?


15

Ich bin ein relativer Linux-Neuling. Ich versuche zu lernen, wie man es benutzt, atdamit ich Aufgaben planen kann, die zu einem späteren Zeitpunkt beginnen, ohne sie zu benutzen sleep. Ich habe in dieser vorherigen Frage nach Hilfe gesucht .

Meine Frage ist, warum in dem folgenden Beispiel-Bash-Skript, das ich erstellt habe, "Laufen" nie - soweit ich das beurteilen kann - auf die Standardausgabe (dh meine Bash-Konsole) gedruckt wird.

#!/bin/bash

echo "Started"

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

echo "Finished"

Die einzige Ausgabe, die ich sehe, ist zum Beispiel:

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

Ist die Antwort auf meine Frage in der Warnung enthalten? Wenn ja, wie unterscheidet /bin/shsich die Standardausgabe?


Versuchen Sie dies:sleep 3m; echo Running
Jasen

Antworten:


18

Denn atführt keine Befehle im Kontext Ihrer angemeldeten Benutzersitzung aus. Die Idee ist, dass Sie einen Befehl so planen können, dass er zu einer beliebigen Zeit ausgeführt wird. Anschließend können Sie sich abmelden und das System kümmert sich um die Ausführung des Befehls zur angegebenen Zeit.

Beachten Sie, dass die Handbuchseite für at(1)speziell (meine Betonung) sagt:

Dem Benutzer wird ein Standardfehler und eine Standardausgabe seiner Befehle, falls vorhanden, zugesandt. E-Mails werden mit dem Befehl / usr / sbin / sendmail gesendet.

Sie sollten also Ihren lokalen Mail-Spool oder, falls dies nicht der Fall ist, die lokalen System-Mail-Protokolle überprüfen. / var / spool / mail / $ USER ist wahrscheinlich ein guter Anfang.

Beachten Sie auch, dass "Gestartet" und "Fertiggestellt" aus dem äußeren Skript stammen und an und für sich überhaupt nichts damit zu tun haben at. Sie könnten sie oder den atAufruf herausnehmen und Sie werden im Wesentlichen das gleiche Ergebnis erhalten.


8

Wie @ MichaelKjörling erklärt hat, werden alle von Ihrem atAuftrag erzeugten Ausgaben erfasst und per E-Mail an Sie gesendet. Wenn auf Ihrer Box kein MTA - Mail Transfer Agent ausgeführt wird, befindet sich die E - Mail möglicherweise in einer Schwebe, und Sie wissen nicht, dass dies atüberhaupt versucht wird.

Ein MTA ist ein Programm wie sendmailoder postfixdas E-Mails an ein geeignetes Ziel "zustellen" kann. In diesem Fall wird es an eine E-Mail-Warteschlange (eine Datei unter dem Verzeichnis /var/spool/mail) auf Ihrem lokalen System gesendet. Jeder Benutzer im System kann eine Warteschlange in diesem Verzeichnis haben.

Wenn ich auf meinem Fedora-System sendmailstarte, kann die Zustellung lokaler E-Mails erfolgen. Normalerweise habe ich es aber ausgeschaltet.

$ sudo service start sendmail

Jetzt können wir sehen, dass meine Mail-Warteschlange für mein Benutzerkonto samlleer ist:

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

Jetzt führen wir den atJob aus:

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

Wir können sehen, dass der Job darauf wartet, ausgeführt zu werden atq:

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

Wenn Sie es nach ein paar Minuten erneut ausführen, sehen Sie, dass der atAuftrag abgeschlossen ist:

$ atq
$

Im Übrigen erhalte ich bei laufendem MTA folgende Meldung in meinem Terminal:

Sie haben neue E-Mails in / var / spool / mail / saml

Also lasst uns nachsehen:

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

Ja, wir haben Post, also lasst es uns überprüfen mit mutt:

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

Wir haben dies im "Posteingang" unserer Mail-Warteschlange:

     ss von mutt's Posteingang

Schauen wir uns diese E-Mail an:

     ss von mutt's msg

Und es hat funktioniert.


@ MichaelKjörling - mutt rulz 8-)
slm

5

Ich verwende Debian 8.1 (jessie).
Sie können den ' at' -Ausgang mit tty an ein Terminal senden.

$ tty
/dev/pts/1

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

Eine Minute später erscheint 'ZZZZZ' in Ihrem Terminal ...


2

Die obigen Antworten sind der Standard / "richtige" Weg, um es zu tun.

Ein weiterer Ansatz, der aus Sicht des "Endbenutzers" einfacher ist, besteht darin, dass geplante oder Hintergrundaufgaben ihre Ausgabe in eine "Protokoll" -Datei schreiben. Die Datei kann sich überall auf Ihrem System befinden, aber wenn die Aufgabe als root ausgeführt wird (von cronusw.), dann irgendwo darunter/var/log ist es ein guter Ort, sie abzulegen.

Ich habe das /var/log/maintVerzeichnis erstellt und es für alle lesbar gemacht. Unter dem Namen "backup" befindet sich eine lesbare Datei, in der ich die Ausgabe meiner Sicherungsskripte protokolliere.

Ich habe mein eigenes Verzeichnis erstellt, damit meine Dateien nicht mit den vom System generierten Dingen verwechselt werden.

Um Dinge dort abzulegen (in Bash):

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

Das >>bewirkt , dass die Nachrichten an die Datei , um sie jedes Mal überschreiben , anstatt angehängt werden.

Wenn mein Skript viel Ausgabe enthält, verwende ich ein Skript oder eine Funktion für die Ausgabe, damit alles auf die gleiche Weise ausgeführt wird. Hier ist meine aktuelle (Overkill-Version): (Das VERBOSE-Zeug ist da, wenn ich das Skript von einem Terminal aus starte und sehen möchte, was zu Debugging-Zwecken vor sich geht.)

#!/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: Einfaches atBeispiel, das in eine Benutzerdatei schreibt

Ich habe es nicht für immer benutzt, also habe ich es mit ein paar einfachen Skripten herausgefunden.

Das erste Skript plant das Ereignis nur mit at. Der Befehl selbst könnte einfach in ein Terminal eingegeben werden, aber ich bin faul - insbesondere, wenn ich ihn beim Testen mehrmals ausführen muss, ohne mich mit dem Befehlsverlauf zu täuschen.

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

Das zweite Skript ist dasjenige, dessen Ausführung geplant ist

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

Ich habe beide Skripte in einem Texteditor erstellt, gespeichert und sie dann jeweils mit ausführbar gemacht chmod 700 script-file-name. Ich habe sie der Einfachheit halber in meinem $HOME/binVerzeichnis abgelegt , aber sie können sich überall befinden, wo mein Benutzer uneingeschränkten Zugriff hat. Ich verwende 700jedes Skript, das nur zum Testen gedacht ist, aber auf einem Einzelnutzersystem kann es genauso gut sein 755.

Ich habe bereits ein Verzeichnis aufgerufen /home/bigbird/log, um die Ausgabe von zu speichern mytest_at_script. Dies kann auch sein, wo Ihr Benutzer vollen Zugriff hat. Stellen Sie einfach sicher, dass es vorhanden ist, bevor das Skript ausgeführt wird, oder lassen Sie es vom Skript erstellen.

Um es auszuführen, habe ich nur sichergestellt, dass die Zeit für den atBefehl mytest_at_runin der Zukunft etwas länger ist, und habe es dann von einem Terminal aus ausgeführt. Ich wartete dann bis es lief und überprüfte den Inhalt von $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$

Ein paar Anmerkungen:

Obwohl ich atvon meinem Benutzer ausgeführt werde, kennt er meine Umgebung wie mein PATHund mein Ausgangsverzeichnis nicht, daher gehe ich nicht davon aus. Ich benutze volle Pfade, wie ich es für jeden cronJob tun würde . Und wenn ich es jemals zu einem cronJob machen will , muss ich nichts ändern, nur um es zum Laufen zu bringen.

Früher habe ich >>in mytest_at_scriptzu append Ausgabe in die Protokolldatei statt , >die es auf jedem Lauf ersetzt haben würde. Verwenden Sie das, was für Ihre Anwendung am besten geeignet ist.


Können Sie mir ein Beispiel für das Schreiben der Ausgabe in eine Protokolldatei mit dem Befehl AT geben? Ich versuche es auf folgende Weise, aber ohne Ergebnis. Zur Zeit + 1 Min. unter> echo "" hallo ">> / home / camsarch / cams_scripts / texsttest. txt um> <EOT>
Pavan Kumar Varma

@PavanKumarVarma - Ein vereinfachtes (getestetes) Beispiel atzum Schreiben in eine Datei wurde hinzugefügt . Sieht so aus, als hätten Sie in Ihrem Beispiel die Aufrufreihenfolge umgekehrt. Ich weiß nicht atso genau , wann ich den Job ausführen soll, also habe ich in naher Zukunft eine Zeit fest programmiert.
Joe
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.