Mengapa perintah 'at' ini tidak mencetak ke output standar?

15

Saya seorang pemula Linux yang relatif. Saya mencoba mempelajari cara menggunakan atsehingga saya dapat menjadwalkan tugas untuk memulai di lain waktu, tanpa menggunakan sleep. Saya telah mencari pertanyaan sebelumnya untuk mendapatkan bantuan.

Pertanyaan saya adalah, dalam skrip bash sampel berikut yang telah saya buat, mengapa "Running" tidak pernah - sejauh yang saya tahu - dicetak ke output standar (yaitu, konsol bash saya)?

#!/bin/bash

echo "Started"

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

echo "Finished"

Satu-satunya keluaran yang saya lihat adalah, misalnya:

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

Apakah jawaban untuk pertanyaan saya ditemukan dalam peringatan? Jika demikian, bagaimana /bin/shperbedaan dari output standar?

Andrew
sumber
coba ini:sleep 3m; echo Running
Jasen

Jawaban:

18

Karena attidak menjalankan perintah dalam konteks sesi pengguna yang Anda masuk. Idenya adalah bahwa Anda dapat menjadwalkan perintah untuk dijalankan pada waktu yang sewenang-wenang, lalu keluar dan sistem akan menjalankan perintah tersebut pada waktu yang ditentukan.

Perhatikan bahwa halaman manual untuk at(1)secara khusus mengatakan (penekanan saya):

Pengguna akan dikirimkan kesalahan standar dan output standar dari perintahnya, jika ada. Mail akan dikirim menggunakan perintah / usr / sbin / sendmail.

Jadi, Anda harus memeriksa gulungan surat lokal Anda atau, gagal itu, log surat sistem lokal. / var / spool / mail / $ USER mungkin merupakan tempat yang baik untuk memulai.

Juga perhatikan bahwa "Memulai" dan "Selesai" berasal dari skrip luar dan dalam dirinya sendiri tidak ada hubungannya atsama sekali. Anda bisa mengambilnya atau atdoa dan pada dasarnya Anda akan mendapatkan hasil yang sama.

sebuah CVn
sumber
8

Seperti yang dijelaskan oleh @ MichaelKjörling, setiap output yang dihasilkan oleh atpekerjaan Anda akan ditangkap dan dikirim kepada Anda melalui email. Jika Anda tidak memiliki MTA - Mail Transfer Agent yang sedang berjalan di kotak Anda, maka surel tersebut mungkin berada di limbo dan Anda tidak akan tahu itu atbahkan sedang mencoba melakukan ini.

MTA, adalah program seperti sendmailatau postfixyang dapat "mengirim" email ke tujuan yang sesuai. Dalam hal ini akan mengirimkannya ke antrian email (file di bawah direktori /var/spool/mail) di sistem lokal Anda. Setiap pengguna pada sistem dapat memiliki antrian di direktori ini.

Pada sistem Fedora saya jika saya mulai sendmailmaka pengiriman surat lokal dapat terjadi. Saya biasanya memilikinya meskipun.

$ sudo service start sendmail

Sekarang kita dapat melihat bahwa antrian email saya untuk akun pengguna saya samlkosong:

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

Jadi sekarang kita menjalankan atpekerjaan:

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

Kita dapat melihat bahwa pekerjaan sedang menunggu untuk dijalankan dengan atq:

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

Menjalankannya lagi setelah beberapa menit kita dapat melihat bahwa atpekerjaan selesai:

$ atq
$

Kebetulan, dengan MTA saya berjalan, saya sekarang mendapatkan pesan ini di terminal saya:

Anda memiliki email baru di / var / spool / mail / saml

Jadi mari kita periksa:

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

Yup, kami punya surat, jadi mari kita periksa menggunakan mutt:

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

Kami memilikinya di "kotak masuk" antrian email kami:

     ss dari inbox mutt

Mari kita periksa email ini:

     ss dari mutt's msg

Dan itu berhasil.

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

Saya menjalankan Debian 8.1 (jessie)
Anda dapat meminta keluaran 'at' ke terminal dengan menggunakan 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>

Satu menit kemudian, dan 'ZZZZZ' akan muncul di terminal Anda ...

AAAfarmclub
sumber
2

Jawaban di atas adalah cara standar / "benar" untuk melakukannya.

Pendekatan lain yang lebih sederhana dari sudut pandang yang lebih "pengguna akhir" adalah memiliki tugas yang dijadwalkan atau latar belakang menulis hasilnya ke file "log". File dapat berada di mana saja di sistem Anda, tetapi jika tugas berjalan sebagai root (dari cron, dll.), Maka di suatu tempat di bawah /var/logadalah tempat yang baik untuk meletakkannya.

Saya membuat /var/log/maintdirektori dan membuatnya dapat dibaca oleh semua orang dan saya memiliki file yang dapat dibaca di bawah yang disebut "cadangan" di mana saya mencatat output dari skrip cadangan saya.

Saya membuat direktori sendiri sehingga file saya tidak tercampur dengan hal-hal yang dihasilkan oleh sistem.

Untuk meletakkan barang di sana (dalam bash):

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

The >>menyebabkan pesan yang akan ditambahkan ke file bukan Timpa setiap kali.

Jika skrip saya memiliki banyak output, saya menggunakan skrip atau fungsi untuk output sehingga semuanya dilakukan dengan cara yang sama. Di bawah ini adalah versi saya saat ini (versi berlebihan): (hal-hal VERBOSE ada ketika saya menjalankan skrip dari terminal dan ingin melihat apa yang terjadi untuk keperluan debugging.)

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

Sunting: atContoh sederhana yang menulis ke file pengguna

Belum pernah menggunakan ini selamanya, jadi saya mengetahuinya dengan beberapa skrip sederhana.

Script pertama hanya menjadwalkan acara menggunakan at. Perintah itu sendiri bisa saja diketik ke terminal, tapi saya malas - terutama ketika saya harus melakukannya berkali-kali saat mengujinya tanpa membodohi sejarah perintah.

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

Script kedua adalah skrip yang dijadwalkan untuk dijalankan

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

Saya membuat kedua skrip dalam editor teks, menyimpannya, dan kemudian membuat mereka masing-masing dieksekusi menggunakan chmod 700 script-file-name. Saya menempatkan keduanya di $HOME/bindirektori saya untuk kenyamanan, tetapi mereka bisa di mana saja pengguna saya memiliki akses penuh. Saya menggunakan 700untuk skrip apa pun yang hanya untuk pengujian, tetapi pada sistem pengguna tunggal, bisa juga begitu 755.

Saya sudah memiliki direktori yang dipanggil /home/bigbird/loguntuk menyimpan output dari mytest_at_script. Ini juga bisa di mana saja pengguna Anda memiliki akses penuh. Pastikan sudah ada sebelum skrip berjalan atau minta skrip membuatnya.

Untuk menjalankannya, saya hanya memastikan waktu untuk atperintah mytest_at_runitu sedikit di masa depan dan kemudian menjalankannya dari terminal. Saya kemudian menunggu sampai berlari dan memeriksa isinya $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$

Beberapa catatan:

Meskipun saya menjalankan atdari pengguna saya, itu tidak tahu lingkungan saya seperti PATHdirektori rumah saya dan saya, jadi saya tidak menganggap itu. Saya menggunakan jalur penuh seperti yang saya lakukan untuk cronpekerjaan apa pun . Dan jika saya ingin membuatnya menjadi cronpekerjaan, saya tidak perlu mengubah apa pun hanya untuk membuatnya berjalan.

Aku digunakan >>dalam mytest_at_scriptoutput append ke file log bukannya >yang akan diganti pada setiap run. Gunakan mana yang paling sesuai dengan aplikasi Anda.

Joe
sumber
dapatkah Anda memberikan saya contoh untuk menulis output ke file log menggunakan perintah AT, saya mencoba dengan cara berikut tetapi tidak ada hasil, sekarang + 1 menit di> echo "" hello ">> / home / camsarch / cams_scripts / texsttest. txt di> <EOT>
Pavan Kumar Varma
@PavanKumarVarma - menambahkan contoh simplistic (teruji) yang digunakan atuntuk menulis ke file. Sepertinya Anda mendapatkan urutan panggilan mundur dalam contoh Anda. Saya tidak pandai mengatakan atkapan harus menjalankan pekerjaan, jadi saya hanya membuat kode waktu dalam waktu dekat.
Joe