วิธีรับทั้ง PIPESTATUS และเอาต์พุตใน bash script


9

ฉันพยายามรับวันที่แก้ไขล่าสุดของไฟล์ด้วยคำสั่งนี้

TM_LOCAL=`ls -l --time-style=long-iso ~/.vimrc | awk '{ print $6" "$7 }'`

TM_LOCAL มีค่าเช่น "2012-05-16 23:18" หลังจากเรียกใช้งานบรรทัดนี้

ฉันต้องการตรวจสอบ PIPESTATUS เพื่อดูว่ามีข้อผิดพลาดหรือไม่ ตัวอย่างเช่นหากไฟล์ไม่มีอยู่lsส่งคืน 2 แต่$?มีค่า 0 เนื่องจากมีค่าส่งคืนawkเป็น

ถ้าฉันรันคำสั่งนี้เพียงอย่างเดียวฉันสามารถตรวจสอบค่าส่งคืนของ ls โดยดูที่ ${PIPESTATUS[0]}

ls -l --time-style=long-iso ~/.vimrc | awk '{ print $6" "$7 }'

แต่$PIPESTATUSไม่ทำงานอย่างที่ฉันคาดไว้ถ้าฉันกำหนดเอาต์พุตให้กับตัวแปรตามตัวอย่างแรก ในกรณีนี้$PIPESTATUSอาร์เรย์มีเพียง 1 องค์ประกอบซึ่งเหมือนกับ$?

ดังนั้นคำถามคือฉันจะได้รับทั้งสอง$PIPESTATUSและกำหนดผลลัพธ์ให้ตัวแปรในเวลาเดียวกันได้อย่างไร

คำตอบ:


8

คุณสามารถทำได้:

TM_LOCAL=$(ls -l --time-style=long-iso ~/.vimrc | \
             awk '{ print $6" "$7 }' ; exit ${PIPESTATUS[0]} )

จากนั้นจะมีรหัสส่งคืนจาก$? lsวิธีนี้ใช้ไม่ได้หากคุณต้องการรหัสส่งคืนจากชิ้นส่วนไปป์มากกว่าหนึ่งชิ้น (แต่คุณสามารถแยกไปป์ไลน์ได้หากเอาต์พุตไม่ใหญ่เกินไปเนื่องจากเป็นที่นี่)

นี่เป็นวิธีที่ค่อนข้างแพงในการรับPIPESTATUSอาร์เรย์เต็มและเอาต์พุต ไม่หรูหรามาก แต่ไม่พบสิ่งอื่น:

result=$(echo -e "a\nb\nc" | \
          ( cat ; exit 1 ) | \
          ( cat ; exit 42 ) ; echo ${PIPESTATUS[@]})
output=$(head -n -1 <<< "$result")
status=($(tail -n 1 <<< "$result"))
echo "Output:"
echo "$output"
echo "Results:"
echo "${status[@]}"

ซึ่งจะช่วยให้:

Output:
a
b
c
Results:
0 1 42

งานนี้ในกรณีของฉัน แต่ฉันก็ยังสงสัยว่าถ้ามีวิธีรับ array pipestatus และผลลัพธ์ที่สมบูรณ์
มุสตาฟาเซร์ดาร์Şanlı

3

ใช้set -o pipefailในการที่จะได้รับมากที่สุดขวาไม่ใช่ศูนย์รหัสทางออกในลำดับคำสั่งประปาเป็นbash $?จากman bash:

หากตั้งค่าส่งคืนของไปป์ไลน์คือค่าของคำสั่งสุดท้าย (ขวาสุด) เพื่อออกด้วยสถานะที่ไม่เป็นศูนย์หรือเป็นศูนย์หากคำสั่งทั้งหมดในการออกจากไปป์ไลน์สำเร็จ ตัวเลือกนี้ถูกปิดใช้งานโดยค่าเริ่มต้น

$?จากนั้นคุณก็สามารถเข้าถึง ใช้set +o pipefailเพื่อปิดการใช้งานอีกครั้ง


2

ฉันถือว่าปัญหาที่นี่คือ PIPESTATUS หายไปอย่างสมบูรณ์ทันทีที่คุณรันคำสั่ง คุณสามารถรับอาร์เรย์ PIPESTATUS ที่สมบูรณ์ใน bash เวอร์ชัน 2 หรือสูงกว่าด้วยวิธีนี้:

declare -a status
status=(${PIPESTATUS[@]})

จากนั้นการเข้าถึง${status[0]}, ${status[1]}ฯลฯ


2

ปัญหาหลักของ "สิ่งที่คุณคาดหวัง" คือคำสั่งใน backquotes จะถูกดำเนินการใน subshell $PIPESTATUSมีอยู่และสถานะที่ส่งคืนจากนั้นจะเป็นไปตามกฎเดียวกันกับที่คุณเรียกใช้งานไฟล์เรียกทำงานเดียว (หรือเชลล์สคริปต์) สถานะของคำสั่ง backquote อยู่ทางด้านขวาสุด (awk )

หากต้องการใช้สิ่งที่ @ Daniel Beckกล่าวให้ตั้งค่าpipefailตัวเลือกใน subshell ดังนี้:

TM_LOCAL=`set -o pipefail; ls -l --time-style=long-iso ~/.vimrc | awk '{ print $6" "$7 }'` ตอนนี้สถานะที่เก็บใน$?ภายหลังจะเป็นสถานะของls(หากไม่ใช่ศูนย์)

อย่างไรก็ตามฉันคิดว่าการif [ -f ~/.vimrc ];ทดสอบที่ชัดเจน... จะสามารถอ่านได้มากขึ้น

คุณไม่สามารถรับเอาต์พุตเป็นตัวแปรและPIPESTATUSส่งคืนโดยไม่มีไฟล์ชั่วคราวสำหรับไฟล์เก่า


0

ฉันต้องการส่งอีเมล fron cron เฉพาะในกรณีที่สถานะทางออกไม่เป็นศูนย์

เคล็ดลับคือการได้รับ stdin ในตอนท้ายของไปป์ไลน์คุณต้องใส่ไว้ใน subshell - แต่ดูเหมือนว่าจะซ่อนค่า PIPESTATUS ...

cron ทดสอบคายบางเอาท์พุทและออกด้วย 1 หรือ 0 ..

./testcron | (test ${PIPESTATUS[0]} -ne 0 || mail -s "testcron output" paul)

อัพเดต: PIPESTATUS ไม่สามารถมองเห็นได้จนกว่าคำสั่งไพพ์ไลน์จะถูกประมวลผล


0

statทางเลือกหนึ่งคือการตรวจสอบสำหรับการดำรงอยู่ของไฟล์ของคุณก่อนที่จะได้รับการปรับเปลี่ยนเวลาที่มีการเรียกร้องให้ ตั้งแต่ statส่งกลับมากกว่าที่คุณต้องการในการประทับเวลาเล็กน้อยคุณสามารถตัดโดยใช้การขยายพารามิเตอร์

ด้วย GNU stat(เช่นบน Linux) คุณสามารถเรียกใช้:

[[ -f ~/.vimrc ]] && TM_LOCAL=$(stat -c '%y' ~/.vimrc 2>/dev/null)
TM_LOCAL=${TM_LOCAL%:*}  # Safe to do, even if stat fails

บน Mac OS X และระบบ BSD อื่น ๆstatไวยากรณ์ต่างกันและสามารถระบุรูปแบบเวลาได้:

[[ -f ~/.vimrc ]] && TM_LOCAL=$(stat -f '%Sm' -t '%Y-%m-%d %H:%M' ~/.vimrc 2>/dev/null)

ในตอนนี้คำตอบของ GNU คืออะไรคุณพูดว่าการเปลี่ยนแปลง$TM_LOCALนั้นปลอดภัย จะปลอดภัยก็ต่อเมื่อคุณคาดว่าจะไม่ได้รับค่าก่อน พูดถึงค่าก่อนหน้านี้2020-02-27 17:14และไม่มี~/.vimrcไฟล์ 2020-02-27 17แล้วคุณจะต้อง ฉันจึงโยงโซ่สองบรรทัดนี้พร้อมกับส่วนเพิ่มเติม&&หรือ (โดยเฉพาะอย่างยิ่งเนื่องจากไม่ชัดเจน) ใช้ifบท
Adam Katz
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.