ฉันจะบันทึกการกระทำของสคริปต์ทุบตีทั้งหมดได้อย่างไร


44

ฉันต้องการบันทึกข้อมูลบันทึกทั้งหมดซึ่งมีทั้งข้อความแสดงข้อผิดพลาดจากเอาต์พุตสคริปต์ของฉันและเปลี่ยนเส้นทางทั้งหมดเป็นไฟล์บันทึก

ฉันมีสคริปต์เหมือนด้านล่าง:

#!/bin/bash
(
echo " `date` : part 1 - start "
ssh -f admin@server.com 'bash /www/htdocs/server.com/scripts/part1.sh logout exit'
echo " `date` : sleep 120"
sleep 120
echo " `date` : part 2 - start"
ssh admin@server.com 'bash /www/htdocs/server.com/scripts/part2.sh logout exit'
echo " `date` : part 3 - start"
ssh admin@server.com 'bash /www/htdocs/server.com/scripts/part3.sh logout exit'
echo " `date` : END"
) | tee -a /home/scripts/cron/logs

ฉันต้องการที่จะเห็นการกระทำทั้งหมดในไฟล์ /home/scripts/cron/logs

แต่ฉันเห็นเฉพาะสิ่งที่ฉันสั่งหลังจาก echo

วิธีการเช็คอินบันทึกคำสั่ง SSH สำเร็จหรือไม่

ฉันต้องการรวบรวมข้อมูลบันทึกทั้งหมด ฉันต้องการสิ่งนี้เพื่อตรวจสอบผลลัพธ์ของทุกคำสั่งในสคริปต์ของฉันเพื่อวิเคราะห์สิ่งที่เกิดขึ้นขณะที่สคริปต์ล้มเหลว


คุณยังสามารถใช้ "สคริปต์" เพื่อดำเนินการนี้ ดูโพสต์นี้: [ที่นี่] [1] [1]: stackoverflow.com/questions/5985060//
xX0v0Xx

คุณจะต้องระมัดระวังกับ errexit - ฉันสังเกตเห็นว่ามันถูกละเว้นหรือข้อผิดพลาดไม่ได้ออกจากสคริปต์เช่น หากคุณมีสิ่งนี้ในสคริปต์: command || dosmthg เมื่อคำสั่งล้มเหลวสคริปต์ไม่ออกทันทีด้วยชุด errexit แต่เพียงแค่เรียกใช้ dosmthg และดำเนินการต่อสคริปต์

คำตอบ:


66

ฉันมักจะใส่สิ่งที่คล้ายกับต่อไปนี้ที่จุดเริ่มต้นของทุกสคริปต์ (โดยเฉพาะถ้ามันจะทำงานเป็น daemon):

#!/bin/bash
exec 3>&1 4>&2
trap 'exec 2>&4 1>&3' 0 1 2 3
exec 1>log.out 2>&1
# Everything below will go to the file 'log.out':

คำอธิบาย:

  1. exec 3>&1 4>&2

    บันทึกไฟล์ descriptors เพื่อให้พวกเขาสามารถเรียกคืนสิ่งที่พวกเขาก่อนที่จะเปลี่ยนเส้นทางหรือใช้ตัวเองเพื่อส่งออกไปยังสิ่งที่พวกเขาก่อนที่จะเปลี่ยนเส้นทางต่อไปนี้

  2. trap 'exec 2>&4 1>&3' 0 1 2 3

    กู้คืนไฟล์ descriptors สำหรับสัญญาณเฉพาะ ไม่จำเป็นโดยทั่วไปเนื่องจากควรเรียกคืนเมื่อออกจากเชลล์ย่อย

  3. exec 1>log.out 2>&1

    เปลี่ยนเส้นทางstdoutไปยังไฟล์log.outแล้วเปลี่ยนเส้นทางไปยังstderr stdoutโปรดทราบว่าการสั่งซื้อมีความสำคัญเมื่อคุณต้องการให้พวกเขาไปที่ไฟล์เดียวกัน stdout จะต้องถูกนำไปก่อนที่จะถูกเปลี่ยนเส้นทางไปstderrstdout

ต่อจากนั้นจะเห็นผลลัพธ์บนคอนโซล (อาจจะ) &3คุณก็สามารถเปลี่ยนเส้นทางไป ตัวอย่างเช่น,

echo "$(date) : part 1 - start" >&3

จะไปที่ใดก็ตามที่stdoutได้รับการแนะนำสันนิษฐานคอนโซลก่อนที่จะดำเนินการบรรทัดที่ 3 ข้างต้น


<< ดีกว่าขอบคุณ! ฉันเพิ่มข้อความเหล่านั้น (exec, trap, exec) ที่จุดเริ่มต้นของสคริปต์และฉันสามารถรับทั้ง stdout และ stderr แต่ปัญหาหนึ่ง: ฉันได้เห็น "ตัวอธิบายไฟล์ 3 (ไพพ์: XXX) รั่วไหลใน some_command" ... โปรดแจ้งให้เราทราบว่าฉันจะหลีกเลี่ยงข้อผิดพลาดเหล่านี้ได้อย่างไร ฉันกำลังใช้ busybox based sh ในบอร์ดที่กำหนดเอง
Kumar

3
กังฟูที่ยอดเยี่ยมที่นี่ !!! - trap 'exec 2>&4 1>&3' 0 1 2 3 RETURNดียิ่งขึ้นคือการใช้งาน RETURN pseudo sigspec file file descriptor ทุกครั้งที่เชลล์ฟังก์ชั่นหรือสคริปต์ทำงานด้วย หรือบิวด์อินต้นทางเสร็จสิ้นการดำเนินการ สำหรับสิ่งนี้ (และด้วยเหตุผลอื่น ๆ ) ในสคริปต์ของฉันฉันเพิ่มเป็น 2 บรรทัดสุดท้าย: return& exit 0- เพียงแค่ 2 เซ็นต์ของฉันรุ่งโรจน์ถึงคุณ @nicerobot!
DavAlPi

มีรายละเอียดจำนวนมากเกี่ยวกับการบันทึกเชลล์สคริปต์ผ่าน varaibles เชลล์ทั่วโลก เราสามารถเลียนแบบการเข้าสู่ระบบในเชลล์สคริปต์ชนิดที่คล้ายกัน: cubicrace.com/2016/03/efficient-logging-mechnism-in-shell.html โพสต์มีรายละเอียดเกี่ยวกับระดับการบันทึกข้อมูลแนะนำเช่น INFO, DEBUG, ERROR รายละเอียดการติดตามเช่นรายการสคริปต์ออกจากสคริปต์รายการฟังก์ชั่นออกจากฟังก์ชั่น
Piyush Chordia

การแจกแจงtrapสัญญาณมีลักษณะแปลกเล็กน้อย โดยปกติแล้วคุณจะต้องรวม15เช่นกัน
tripleee

1
@PiyushChordia แก้ไขลิงก์: cubicrace.com/2016/03/efficient-logging-mechnism-in-shell.html
vigilancer

14

ที่จะได้รับการส่งออก SSH เพื่อ logfile ของคุณคุณต้องเปลี่ยนเส้นทางไปยังstderr stdoutคุณสามารถทำได้โดยต่อท้าย2>&1สคริปต์ทุบตี

มันควรมีลักษณะเช่นนี้:

#!/bin/bash
(
...
) 2>&1 | tee ...

เมื่อสิ่งนี้ไม่แสดงข้อความในลำดับที่ถูกต้องลองเพิ่ม subshell อื่น:

#!/bin/bash
((
...
) 2>&1) | tee ...

1
มันใช้งานได้ดี ที่จริงคุณสามารถกำกับทั้ง stdout และ stderr ด้วย:( ... ) |& tee output.log
Noam Manos

12

เมื่อฉันอ่านคำถามของคุณคุณไม่ต้องการบันทึกผลลัพธ์ แต่ลำดับของคำสั่งทั้งหมดซึ่งในกรณีนี้คำตอบอื่น ๆ จะไม่ช่วยคุณ

เรียกใช้เชลล์สคริปต์ด้วย -x เพื่อส่งออกทุกอย่าง:

sh -x foo.sh

เข้าสู่ไฟล์ที่คุณต้องการด้วย:

sh -x foo.sh >> /home/scripts/cron/logs


2
+1 สำหรับ -x ตัวเลือก
Coc

10

ใน bash คุณสามารถใส่set -xและมันจะพิมพ์ทุกคำสั่งที่มันรัน (และตัวแปร bash) หลังจากนั้น set +xคุณสามารถเปิดออกด้วย

หากคุณต้องการที่จะหวาดระแวงคุณสามารถใส่set -o errexitในสคริปต์ของคุณ นี่หมายความว่าสคริปต์จะล้มเหลวและหยุดทำงานหากคำสั่งเดียวส่งคืนโค้ดออกที่ไม่เป็นศูนย์ซึ่งเป็นวิธีมาตรฐานของยูนิกซ์ในการส่งสัญญาณว่ามีบางอย่างผิดปกติ

หากคุณต้องการได้รับบันทึกที่ดีกว่าคุณควรดูtsในmoreutilsแพ็คเกจ debian / ubuntu มันจะนำหน้าแต่ละบรรทัดด้วยการประทับเวลาและพิมพ์ออกมา คุณจะเห็นได้ว่าเกิดอะไรขึ้น


1
"set -o errexit" จะต้องเหมือนกับ "set -e"
Ajith Antony

0

ทำตามสิ่งที่คนอื่นพูดไว้ชุดคู่มือเป็นทรัพยากรที่ดี ฉันใส่:

#!/usr/bin/env bash
exec 1> command.log 2>&1
set -x

ที่ด้านบนของสคริปต์ฉันต้องการที่จะไปหรือset -exถ้ามันควรออกจากข้อผิดพลาด


สิ่งนี้จะช่วยให้บันทึก ssh และการดำเนินการคำสั่งสำเร็จหรือไม่
asktyagi

การทดสอบกับสคริปต์จำลองของ OP นั้นจะบันทึกแต่ละคำสั่งและผลลัพธ์ใด ๆ : การหมดเวลา ssh, โดเมนไม่ถูกต้อง ฯลฯ หรือสำหรับที่อยู่ ssh ที่ถูกต้องจะบันทึกคำสั่งในเชลล์ระยะไกล หากต้องการข้อมูลเพิ่มเติมเกี่ยวกับการเข้าสู่ระบบ SSH อาจจะssh -vv?
dragon951
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.