Tại sao lệnh 'at' này không in ra đầu ra tiêu chuẩn?


15

Tôi là một người mới làm quen với Linux. Tôi đang cố gắng học cách sử dụng atđể tôi có thể lên lịch các nhiệm vụ để bắt đầu sau, mà không cần sử dụng sleep. Tôi đã xem xét câu hỏi trước đây để được giúp đỡ.

Câu hỏi của tôi là, trong tập lệnh bash mẫu sau mà tôi đã tạo, tại sao "Chạy" không bao giờ - theo như tôi có thể nói - được in ra đầu ra tiêu chuẩn (ví dụ: bảng điều khiển bash của tôi)?

#!/bin/bash

echo "Started"

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

echo "Finished"

Đầu ra duy nhất tôi thấy là, ví dụ:

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

Là câu trả lời cho câu hỏi của tôi được tìm thấy trong cảnh báo? Nếu vậy, làm thế nào /bin/shkhác với đầu ra tiêu chuẩn?


thử cái này:sleep 3m; echo Running
Jasen

Câu trả lời:


18

Bởi vì atkhông thực thi các lệnh trong ngữ cảnh phiên người dùng đã đăng nhập của bạn. Ý tưởng là bạn có thể lên lịch để chạy lệnh vào một thời điểm tùy ý, sau đó đăng xuất và hệ thống sẽ đảm nhiệm việc chạy lệnh tại thời điểm được chỉ định.

Lưu ý rằng trang hướng dẫn at(1)cụ thể nói (nhấn mạnh của tôi):

Người dùng sẽ được gửi thư lỗi tiêu chuẩn và đầu ra tiêu chuẩn từ các lệnh của mình, nếu có. Thư sẽ được gửi bằng lệnh / usr / sbin / sendmail.

Vì vậy, bạn nên kiểm tra bộ đệm thư cục bộ của bạn hoặc, không thành công, nhật ký thư hệ thống cục bộ. / var / spool / mail / $ USER có lẽ là một nơi tốt để bắt đầu.

Cũng lưu ý rằng "Bắt đầu" và "Hoàn thành" bắt nguồn từ tập lệnh bên ngoài và bản thân chúng không liên quan gì atcả. Bạn có thể loại bỏ chúng hoặc atlời mời và về cơ bản bạn sẽ nhận được kết quả tương tự.


8

Như @ MichaelKjorling đã giải thích, bất kỳ đầu ra nào do atcông việc của bạn tạo ra sẽ được ghi lại và gửi cho bạn qua email. Nếu bạn không có MTA - Đại lý chuyển thư đang chạy trên hộp của mình thì email có thể ở trạng thái lấp lửng và bạn sẽ không biết rằng atthậm chí đang cố gắng thực hiện việc này.

MTA, là một chương trình như sendmailhoặc postfixcó thể "gửi" email đến một địa điểm thích hợp. Trong trường hợp này, nó sẽ gửi nó đến một hàng đợi thư (một tệp trong thư mục /var/spool/mail) trên hệ thống cục bộ của bạn. Mỗi người dùng trên hệ thống có thể có một hàng đợi trong thư mục này.

Trên hệ thống Fedora của tôi nếu tôi khởi động sendmailthì việc gửi thư địa phương có thể xảy ra. Tôi thường có nó tắt mặc dù.

$ sudo service start sendmail

Bây giờ chúng ta có thể thấy rằng hàng đợi thư cho tài khoản người dùng của tôi samltrống:

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

Vì vậy, bây giờ chúng tôi điều hành atcông việc:

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

Chúng ta có thể thấy rằng công việc đang chờ để chạy với atq:

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

Chạy lại sau vài phút, chúng ta có thể thấy rằng atcông việc đã hoàn thành:

$ atq
$

Ngẫu nhiên, với MTA của tôi đang chạy, bây giờ tôi nhận được thông báo này trong thiết bị đầu cuối của mình:

Bạn có thư mới trong / var / spool / mail / saml

Vì vậy, hãy kiểm tra:

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

Bạn đã có thư, vì vậy hãy kiểm tra bằng cách sử dụng mutt:

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

Chúng tôi có cái này trong "hộp thư đến" của hàng đợi thư của chúng tôi:

     ss của hộp thư đến của mutt

Hãy xem email này:

     ss của tin nhắn của mutt

Va no đa hoạt động.


@ MichaelKjorling - mutt rulz 8-)
slm

5

Tôi đang chạy Debian 8.1 (jessie)
Bạn có thể đưa đầu ra 'at' đến một thiết bị đầu cuối bằng cách sử dụng 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>

Một phút sau, và 'ZZZZZ' sẽ xuất hiện trong thiết bị đầu cuối của bạn ...


2

Các câu trả lời trên là cách chuẩn / "đúng" để làm điều đó.

Một cách tiếp cận khác đơn giản hơn từ quan điểm "người dùng cuối" hơn là có bất kỳ tác vụ nền hoặc lịch trình nào ghi đầu ra của nó vào tệp "nhật ký". Tệp có thể ở bất cứ đâu trên hệ thống của bạn, nhưng nếu tác vụ đang chạy dưới quyền root (từ cron, v.v.), thì một nơi nào đó bên dưới /var/loglà một nơi tốt để đặt nó.

Tôi đã tạo /var/log/maintthư mục và làm cho mọi người có thể đọc được và tôi có một tệp có thể đọc được dưới tên gọi là "bản sao lưu" nơi tôi ghi nhật ký đầu ra từ các tập lệnh sao lưu của mình.

Tôi đã tạo thư mục của riêng mình để các tệp của tôi không bị lẫn vào những thứ do hệ thống tạo ra.

Để đặt công cụ ở đó (trong bash):

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

Các >>nguyên nhân gây các tin nhắn được nối thêm vào các tập tin thay vì ghi đè lên nó mỗi lần.

Nếu tập lệnh của tôi có nhiều đầu ra, tôi sử dụng tập lệnh hoặc hàm cho đầu ra để mọi thứ được thực hiện như nhau. Dưới đây là hiện tại của tôi (phiên bản quá mức): (Nội dung ĐỘNG TỪ có sẵn khi tôi đang chạy tập lệnh từ thiết bị đầu cuối và muốn xem những gì đang diễn ra cho mục đích gỡ lỗi.)

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

Chỉnh sửa: atVí dụ đơn giản ghi vào tệp người dùng

Không sử dụng nó mãi mãi, vì vậy tôi đã tìm ra nó với một vài kịch bản đơn giản.

Kịch bản đầu tiên chỉ lên lịch sự kiện bằng cách sử dụng at. Bản thân lệnh chỉ có thể được gõ vào một thiết bị đầu cuối, nhưng tôi lười biếng - đặc biệt là khi tôi phải thực hiện nó nhiều lần trong khi kiểm tra nó mà không bị lừa với lịch sử lệnh.

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

Kịch bản thứ hai là kịch bản dự kiến ​​chạy

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

Tôi đã tạo cả hai tập lệnh trong một trình soạn thảo văn bản, lưu chúng và sau đó làm cho chúng thực thi từng tập lệnh bằng cách sử dụng chmod 700 script-file-name. Tôi đặt cả hai trong $HOME/binthư mục của tôi để thuận tiện, nhưng chúng có thể là bất cứ nơi nào người dùng của tôi có quyền truy cập đầy đủ. Tôi sử dụng 700cho bất kỳ tập lệnh nào chỉ để thử nghiệm, nhưng trên một hệ thống người dùng, nó cũng có thể là755 .

Tôi đã có một thư mục được gọi /home/bigbird/logđể lưu đầu ra từ mytest_at_script. Đây cũng có thể là bất cứ nơi nào người dùng của bạn có quyền truy cập đầy đủ. Chỉ cần chắc chắn rằng nó tồn tại trước khi tập lệnh chạy hoặc có tập lệnh tạo nó.

Để chạy nó, tôi chỉ đảm bảo rằng thời gian cho atlệnh trong mytest_at_runmột chút trong tương lai và sau đó chạy nó từ một thiết bị đầu cuối. Sau đó tôi đợi cho đến khi nó chạy và kiểm tra nội dung của $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$

Một vài lưu ý:

Mặc dù tôi đang chạy attừ người dùng của mình, nhưng nó không biết môi trường của tôi như PATHthư mục nhà của tôi và vì vậy tôi không cho rằng điều đó. Tôi sử dụng các đường dẫn đầy đủ như tôi sẽ làm cho bất kỳ croncông việc. Và nếu tôi muốn làm cho nó mộtcron công việc, tôi sẽ không phải thay đổi bất cứ điều gì chỉ để làm cho nó chạy.

Tôi đã sử dụng >>trong mytest_at_scriptsản lượng append vào file log thay vì >đó sẽ thay thế nó trên mỗi chạy. Sử dụng cái nào phù hợp với ứng dụng của bạn nhất.


bạn có thể cung cấp cho tôi bất kỳ ví dụ nào để ghi đầu ra vào tệp nhật ký bằng lệnh AT không, tôi đang thử theo cách sau nhưng không có kết quả, lúc này + 1 phút tại> echo "" xin chào ">> / home / camsarch / cams_scripts / texsttest. txt tại> <EOT>
Pavan Kumar Varma

@PavanKumarVarma - đã thêm một ví dụ đơn giản (đã kiểm tra) bằng cách sử dụng atđể ghi vào tệp. Có vẻ như bạn có chuỗi cuộc gọi ngược trong ví dụ của bạn. Tôi không giỏi nói atkhi nào nên điều hành công việc, vì vậy tôi chỉ khó mã hóa một thời gian trong tương lai rất gần.
Joe
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.