เหตุใดคำสั่ง 'at' นี้จึงไม่พิมพ์ไปยังเอาต์พุตมาตรฐาน


15

ฉันเป็นสามเณร Linux ญาติ ฉันพยายามที่จะเรียนรู้วิธีการใช้เพื่อที่ฉันสามารถกำหนดการงานที่จะเริ่มต้นในเวลาต่อมาโดยไม่ต้องใช้at sleepฉันได้ดูคำถามก่อนหน้านี้เพื่อขอความช่วยเหลือ

คำถามของฉันคือในสคริปต์ทุบตีตัวอย่างต่อไปนี้ที่ฉันสร้างขึ้นทำไม"กำลังรัน"ไม่เคย - เท่าที่ฉันสามารถบอกได้ - พิมพ์ไปยังเอาต์พุตมาตรฐาน (เช่นคอนโซลทุบตีของฉัน)

#!/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แตกต่างจากเอาต์พุตมาตรฐานอย่างไร


ลองนี้:sleep 3m; echo Running
Jasen

คำตอบ:


18

เนื่องจากatไม่ได้ดำเนินการคำสั่งในบริบทของเซสชันผู้ใช้ที่ล็อกอินของคุณ แนวคิดคือคุณสามารถกำหนดเวลาให้คำสั่งรันในเวลาใดก็ได้จากนั้นออกจากระบบและระบบจะดูแลการเรียกใช้คำสั่งตามเวลาที่กำหนด

โปรดทราบว่าหน้าคู่มือสำหรับat(1)พูดโดยเฉพาะ (เน้นของฉัน):

ผู้ใช้จะได้รับข้อผิดพลาดมาตรฐานทางไปรษณีย์และเอาต์พุตมาตรฐานจากคำสั่งของเขาหากมี เมลจะถูกส่งโดยใช้คำสั่ง / usr / sbin / sendmail

ดังนั้นคุณควรตรวจสอบสปูลเมลโลคัลของคุณหรือหากไม่สามารถบันทึกเมลของระบบโลคัล / var / spool / mail / $ USER น่าจะเป็นจุดเริ่มต้นที่ดี

นอกจากนี้โปรดทราบว่า "เริ่มต้น" และ "เสร็จสิ้น" มีต้นกำเนิดมาจากสคริปต์ภายนอกและในตัวของมันเองไม่มีอะไรเกี่ยวข้องatเลย คุณสามารถนำพวกเขาออกมาหรือการatเรียกร้องและคุณจะได้รับผลลัพธ์ที่เหมือนกัน


8

ดังที่ @ MichaelKjörlingได้อธิบายเอาท์พุทใด ๆ ที่ผลิตโดยคุณ atงานจะถูกจับและส่งถึงคุณทางอีเมล หากคุณไม่มีMTA - Mail Transfer Agent ที่อยู่ในกล่องของคุณอีเมลอาจอยู่ในบริเวณขอบรกและคุณจะไม่รู้ว่าatกำลังพยายามทำเช่นนี้

MTA เป็นโปรแกรมเช่น sendmailหรือ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 ของกล่องจดหมายของ mutt

ลองดูอีเมลนี้:

     ผงชูรสของ mutt

และมันก็ใช้งานได้


@ MichaelKjörling - mutt rulz 8-)
slm

5

ฉันใช้ Debian 8.1 (jessie)
คุณสามารถให้ผลลัพธ์ 'at' ไปยังเทอร์มินัลโดยใช้ 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>

หนึ่งนาทีต่อมาและ 'ZZZZZ' จะปรากฏขึ้นในเครื่องของคุณ ...


2

คำตอบข้างต้นเป็นวิธีการมาตรฐาน / "ถูกต้อง"

อีกวิธีที่ง่ายกว่าจากมุมมอง "ผู้ใช้ปลายทาง" มากขึ้นคือการกำหนดเวลาหรืองานพื้นหลังให้เขียนเอาต์พุตไปยังไฟล์ "บันทึก" ไฟล์สามารถอยู่ที่ใดก็ได้ในระบบของคุณ แต่หากงานกำลังทำงานในฐานะรูท (จากcronฯลฯ ) แสดงว่าที่ใดที่หนึ่งภายใต้/var/logเป็นสถานที่ที่ดีที่จะวางไว้

ฉันสร้าง/var/log/maintไดเรกทอรีและทำให้ทุกคนสามารถอ่านได้และฉันมีไฟล์ที่อ่านได้ภายใต้ชื่อ "backup" ซึ่งฉันบันทึกผลลัพธ์จากสคริปต์สำรองของฉัน

ฉันสร้างไดเรกทอรีของตัวเองเพื่อไม่ให้ไฟล์ปะปนกับสิ่งต่าง ๆ ที่ระบบสร้างขึ้น

ในการใส่สิ่งที่มี (ในทุบตี):

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

>>ทำให้เกิดข้อความที่จะผนวกเข้ากับไฟล์แทนการเขียนทับในแต่ละครั้ง

หากสคริปต์ของฉันมีเอาต์พุตจำนวนมากฉันจะใช้สคริปต์หรือฟังก์ชันเพื่อเอาท์พุทดังนั้นทุกอย่างก็จะเหมือนเดิม ด้านล่างคือปัจจุบันของฉัน (เวอร์ชั่น overkill): (สิ่ง 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การส่งออกผนวกไปยังแฟ้มบันทึกแทน>ซึ่งจะมีการแทนที่มันในทุกระยะ ใช้อย่างใดอย่างหนึ่งที่เหมาะสมกับใบสมัครของคุณที่ดีที่สุด


คุณสามารถให้ฉันตัวอย่างเพื่อเขียนผลลัพธ์ไปยังล็อกไฟล์โดยใช้คำสั่ง AT ฉันพยายามทำตามวิธี แต่ไม่มีผลตอนนี้ + 1 นาทีที่> echo "" hello ">> / home / camsarch / cams_scripts / texsttest txt ที่> <EOT>
Pavan Kumar Varma

@PavanKumarVarma - เพิ่มตัวอย่างง่าย ๆ (ทดสอบแล้ว) โดยใช้atเพื่อเขียนไปยังไฟล์ ดูเหมือนว่าคุณมีลำดับการโทรย้อนกลับในตัวอย่างของคุณ ฉันไม่ค่อยถนัดในการบอกatเวลาที่จะทำงานดังนั้นฉันจึงเขียนรหัสยาก ๆ ในอนาคตอันใกล้นี้
โจ
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.