ไพพ์เอาต์พุตและสถานะการดักจับใน Bash


420

ฉันต้องการรันคำสั่งที่รันเป็นเวลานานใน Bash และทั้งคู่ก็จับสถานะทางออกของมันและเอาท์พุทของมันที

ดังนั้นฉันทำสิ่งนี้:

command | tee out.txt
ST=$?

ปัญหาคือตัวแปร ST รวบรวมสถานะการออกของteeและไม่ใช่คำสั่ง ฉันจะแก้ปัญหานี้ได้อย่างไร

โปรดทราบว่าคำสั่งนั้นใช้เวลานานและการเปลี่ยนเส้นทางเอาต์พุตไปยังไฟล์เพื่อดูในภายหลังไม่ใช่วิธีแก้ปัญหาที่ดีสำหรับฉัน


1
[["$ {PIPESTATUS [@]}" = ~ [^ 0 \]]] && echo -e "พบข้อผิดพลาด" || echo -e "ไม่ตรงกัน - ดีทั้งหมด" นี่จะทดสอบค่าทั้งหมดของอาร์เรย์ในครั้งเดียวและให้ข้อความแสดงข้อผิดพลาดหากค่าไพพ์ใด ๆ ที่ส่งคืนไม่ใช่ศูนย์ นี่เป็นโซลูชันทั่วไปที่มีประสิทธิภาพสำหรับการตรวจจับข้อผิดพลาดในสถานการณ์ที่วางท่อ
Brian S. Wilson

คำตอบ:


519

มีตัวแปรทุบตีภายในที่เรียกว่าเป็น$PIPESTATUS; เป็นอาร์เรย์ที่เก็บสถานะการออกของแต่ละคำสั่งไว้ในขั้นตอนสุดท้ายของคำสั่ง

<command> | tee out.txt ; test ${PIPESTATUS[0]} -eq 0

หรือทางเลือกอื่นที่ใช้งานได้กับเชลล์อื่น ๆ (เช่น zsh) ก็คือการเปิดใช้งาน pipefail:

set -o pipefail
...

ตัวเลือกแรกไม่ทำงานzshเนื่องจากมีไวยากรณ์ที่แตกต่างกันเล็กน้อย


21
มีคำอธิบายที่ดีด้วยตัวอย่างของ PIPESTATUS และ Pipefail นี่คือunix.stackexchange.com/a/73180/7453
slm

18
หมายเหตุ: $ PIPESTATUS [0] เก็บสถานะการออกของคำสั่งแรกในไพพ์ $ PIPESTATUS [1] สถานะการออกของคำสั่งที่สองและอื่น ๆ
simpleuser

18
แน่นอนว่าเราต้องจำไว้ว่านี่เป็น Bash-specific: ถ้าฉันเขียนสคริปต์ให้ทำงานบนการติดตั้ง "sh" ของ BusyBox บนอุปกรณ์ Android ของฉันหรือบนแพลตฟอร์มฝังตัวอื่นที่ใช้ "sh" ตัวแปรนี้จะไม่ทำงาน
Asfand Qazi

4
สำหรับผู้ที่มีความกังวลเกี่ยวกับการขยายตัวของตัวแปรที่ไม่ได้ระบุไว้: สถานะการออกจะเป็นจำนวนเต็ม 8 บิตแบบไม่ได้ลงนามใน Bashดังนั้นจึงไม่จำเป็นต้องอ้างถึง นี้ถือภายใต้ระบบปฏิบัติการยูนิกซ์ทั่วไปเกินไปที่ออกจากสถานะถูกกำหนดให้เป็น 8 บิตอย่างชัดเจนและมันจะถือว่าไม่ได้ลงทะเบียนได้โดย POSIX ตัวเองเช่นเมื่อกำหนดของมันปฏิเสธตรรกะ
Palec

3
exit ${PIPESTATUS[0]}นอกจากนี้คุณยังสามารถใช้
Chaoran

142

การใช้ bash's set -o pipefailนั้นมีประโยชน์

pipefail: ค่าส่งคืนของไปป์ไลน์คือสถานะของคำสั่งสุดท้ายเพื่อออกโดยมีสถานะไม่เป็นศูนย์หรือเป็นศูนย์หากไม่มีคำสั่งออกจากสถานะไม่เป็นศูนย์


23
ในกรณีที่คุณไม่ต้องการแก้ไขการตั้งค่า pipefail ของสคริปต์ทั้งหมดคุณสามารถตั้งค่าตัวเลือกได้เฉพาะ:( set -o pipefail; command | tee out.txt ); ST=$?
Jaan

7
@Jaan สิ่งนี้จะเรียกใช้เชลล์ย่อย หากคุณต้องการหลีกเลี่ยงปัญหานั้นคุณสามารถทำได้set -o pipefailจากนั้นทำคำสั่งจากนั้นทำทันทีset +o pipefailเพื่อยกเลิกการตั้งค่าตัวเลือก
Linus Arver

2
หมายเหตุ: ผู้โพสต์คำถามไม่ต้องการ "รหัสทางออกทั่วไป" ของไปป์เขาต้องการรหัสส่งคืนของ 'คำสั่ง' กับ-o pipefailเขาจะรู้ว่าท่อล้มเหลว แต่ถ้าทั้ง 'command' และ 'tee' ล้มเหลวเขาจะได้รับรหัสทางออกจาก 'tee'
t0r0X

@LinusArver จะไม่ล้างรหัสออกเนื่องจากเป็นคำสั่งที่ทำสำเร็จหรือไม่
carlin.scott

126

วิธีแก้ปัญหาโง่: เชื่อมต่อพวกเขาผ่านไปป์ที่มีชื่อ (mkfifo) จากนั้นคำสั่งสามารถรันครั้งที่สอง

 mkfifo pipe
 tee out.txt < pipe &
 command > pipe
 echo $?

20
นี่เป็นคำตอบเดียวในคำถามนี้ที่ใช้ได้กับsh Unix shell อย่างง่าย ขอบคุณ!
JamesThomasMoon1979

3
@DaveKennedy: เป็นใบ้ใน "ชัดเจนไม่ต้องใช้ความรู้ที่ซับซ้อนของ bash syntax"
EFraim

10
ในขณะที่คำตอบของ bash นั้นสง่างามยิ่งขึ้นเมื่อคุณได้รับประโยชน์จากความสามารถพิเศษของ bash แต่นี่เป็นโซลูชันข้ามแพลตฟอร์มที่มากกว่า นอกจากนี้ยังเป็นสิ่งที่ควรค่าแก่การพิจารณาโดยทั่วไปเมื่อใดก็ตามที่คุณทำคำสั่งที่ใช้เวลานานท่อชื่อนั้นมักจะเป็นวิธีที่ยืดหยุ่นที่สุด เป็นที่น่าสังเกตว่าบางระบบไม่มีmkfifoและอาจต้องใช้แทนmknod -pหากฉันจำได้ถูกต้อง
Haravikk

3
บางครั้งเมื่อมีการล้นสแต็คก็มีคำตอบที่คุณจะถอนรากถอนโคนร้อยครั้งดังนั้นผู้คนจะหยุดทำสิ่งอื่นที่ไม่สมเหตุสมผลนี่เป็นหนึ่งในนั้น ขอบคุณครับ
Dan Chase

1
ในกรณีที่มีคนที่มีปัญหากับmkfifoหรือในคำสั่งของฉันที่เหมาะสมกรณีการสร้างแฟ้มท่อเป็นmknod -p mknod FILE_NAME p
Karol Gil

36

มีอาร์เรย์ที่ให้สถานะการออกของแต่ละคำสั่งในไพพ์

$ cat x| sed 's///'
cat: x: No such file or directory
$ echo $?
0
$ cat x| sed 's///'
cat: x: No such file or directory
$ echo ${PIPESTATUS[*]}
1 0
$ touch x
$ cat x| sed 's'
sed: 1: "s": substitute pattern can not be delimited by newline or backslash
$ echo ${PIPESTATUS[*]}
0 1

26

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

สถานการณ์:

someprog | filter

คุณต้องการสถานะออกจากและเอาท์พุทจากsomeprogfilter

นี่คือทางออกของฉัน:

((((someprog; echo $? >&3) | filter >&4) 3>&1) | (read xs; exit $xs)) 4>&1

echo $?

ดูคำตอบของฉันสำหรับคำถามเดียวกันใน unix.stackexchange.comสำหรับคำอธิบายโดยละเอียดและทางเลือกอื่นที่ไม่มีซับเซลล์และคำเตือนบางประการ


20

โดยการรวมPIPESTATUS[0]และผลลัพธ์ของการดำเนินการexitคำสั่งใน subshell คุณสามารถเข้าถึงค่าส่งคืนของคำสั่งเริ่มต้นของคุณโดยตรง:

command | tee ; ( exit ${PIPESTATUS[0]} )

นี่คือตัวอย่าง:

# the "false" shell built-in command returns 1
false | tee ; ( exit ${PIPESTATUS[0]} )
echo "return value: $?"

จะให้:

return value: 1


4
ขอบคุณสิ่งนี้ทำให้ฉันสามารถใช้การสร้าง: VALUE=$(might_fail | piping)ซึ่งจะไม่ตั้ง PIPESTATUS ในเชลล์หลัก แต่จะตั้ง errorlevel โดยใช้: VALUE=$(might_fail | piping; exit ${PIPESTATUS[0]})ฉันต้องการฉันต้องการ
vaab

@vaab ไวยากรณ์นั้นดูดีมาก แต่ฉันสับสนว่า 'การไพพ์' หมายถึงอะไรในบริบทของคุณ นั่นเป็นเพียงที่หนึ่งจะทำ 'ที' หรือการประมวลผลใด ๆ ในผลลัพธ์ของ might_fail หรือไม่? TY!
AnneTheAgile

1
@AnneTheAgile 'piping' ในตัวอย่างของฉันหมายถึงคำสั่งที่คุณไม่ต้องการเห็น errlvl ตัวอย่างเช่น: หนึ่งในหรือชุดค่าผสมใด ๆ ของ 'tee', 'grep', 'sed', ... มันไม่ใช่เรื่องแปลกที่คำสั่ง piping เหล่านี้จะหมายถึงการจัดรูปแบบหรือแยกข้อมูลจากเอาต์พุตขนาดใหญ่หรือเอาต์พุตบันทึกของ main command: คุณมีความสนใจใน errlevel ของคำสั่งหลัก (อันที่ฉันเรียกว่า 'may_fail' ในตัวอย่างของฉัน) แต่ถ้าไม่มีการสร้างการมอบหมายทั้งหมดจะส่งคืน errlvl ของคำสั่ง piped สุดท้ายซึ่งไม่มีความหมาย ชัดเจนกว่านี้ไหม
vaab

command_might_fail | grep -v "line_pattern_to_exclude" || exit ${PIPESTATUS[0]}ในกรณีที่ไม่ได้ที แต่กรอง grep
user1742529

12

ดังนั้นฉันจึงอยากให้คำตอบเหมือน Lesmana แต่ฉันคิดว่าของฉันอาจจะง่ายกว่าและบริสุทธิ์กว่าเล็กน้อยจาก Bourne-shell solution:

# You want to pipe command1 through command2:
exec 4>&1
exitstatus=`{ { command1; printf $? 1>&3; } | command2 1>&4; } 3>&1`
# $exitstatus now has command1's exit status.

ฉันคิดว่านี่เป็นคำอธิบายที่ดีที่สุดจากภายในออก - command1 จะดำเนินการและพิมพ์เอาต์พุตปกติบน stdout (file descriptor 1) จากนั้นเมื่อเสร็จแล้ว printf จะดำเนินการและพิมพ์รหัสทางออกของ icommand1 บน stdout แต่ stdout นั้นถูกเปลี่ยนเส้นทางไป ตัวอธิบายไฟล์ 3.

ในขณะที่ command1 กำลังทำงาน stdout ของมันจะถูกไพพ์ไปที่ command2 (เอาต์พุตของ printf ไม่ทำให้เป็น command2 เพราะเราส่งไปที่ file descriptor 3 แทนที่จะเป็น 1 ซึ่งเป็นสิ่งที่ pipe อ่าน จากนั้นเราเปลี่ยนเส้นทางเอาต์พุตของ command2 ไปยัง file descriptor 4 เพื่อให้มันยังคงอยู่จาก file descriptor 1 - เพราะเราต้องการ file descriptor 1 ฟรีอีกเล็กน้อยในภายหลังเพราะเราจะนำเอา printf บน file descriptor 3 1 - เพราะนั่นคือสิ่งที่การทดแทนคำสั่ง (backticks) จะจับภาพและนั่นคือสิ่งที่จะถูกวางลงในตัวแปร

บิตสุดท้ายของเวทมนตร์คือสิ่งแรก exec 4>&1เราทำในฐานะคำสั่งแยกต่างหาก - มันเปิดไฟล์ descriptor 4 เป็นสำเนาของ stdout ของเปลือกนอก การทดแทนคำสั่งจะจับสิ่งที่เขียนบนมาตรฐานออกมาจากมุมมองของคำสั่งภายใน - แต่เนื่องจากเอาต์พุตของ command2 จะไปยังไฟล์ descriptor 4 เท่าที่เกี่ยวข้องกับการทดแทนคำสั่งการแทนที่คำสั่งจะไม่จับ - แต่เมื่อมัน ได้รับ "out" ของการทดแทนคำสั่งมันยังคงมีประสิทธิภาพไปที่ file descriptor โดยรวมของสคริปต์ 1

(ใน exec 4>&1จะต้องมีคำสั่งแยกต่างหากเพราะเชลล์ทั่วไปจำนวนมากไม่ชอบเมื่อคุณพยายามเขียนไปยังไฟล์ descriptor ภายในการทดแทนคำสั่งที่เปิดในคำสั่ง "ภายนอก" ที่ใช้การทดแทนดังนั้นนี่คือ วิธีพกพาที่ง่ายที่สุดที่จะทำ)

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

นอกจากนี้ตามที่ฉันเข้าใจ$?จะยังคงมีโค้ดส่งคืนของคำสั่งที่สองในไพพ์เนื่องจากการกำหนดตัวแปรการแทนที่คำสั่งและคำสั่งผสมนั้นโปร่งใสทั้งหมดในโค้ดส่งคืนของคำสั่งภายในดังนั้นสถานะการส่งคืนของ command2 ควรแพร่กระจายออกไป - สิ่งนี้และไม่ต้องกำหนดฟังก์ชั่นเพิ่มเติมคือเหตุผลที่ฉันคิดว่านี่อาจเป็นทางออกที่ดีกว่าที่ lesmana เสนอ

ตามที่ระบุใน lesmana lesmana อาจเป็นไปได้ว่าคำสั่ง 1 จะจบลงด้วยการใช้ file descriptors 3 หรือ 4 เพื่อให้มีประสิทธิภาพมากขึ้นคุณจะต้อง:

exec 4>&1
exitstatus=`{ { command1 3>&-; printf $? 1>&3; } 4>&- | command2 1>&4; } 3>&1`
exec 4>&-

โปรดทราบว่าฉันใช้คำสั่งผสมในตัวอย่างของฉัน แต่ใช้ subshells (การใช้( )แทน{ }จะใช้ได้แม้ว่าอาจจะมีประสิทธิภาพน้อยกว่า)

คำสั่งสืบทอดไฟล์ descriptor จากกระบวนการที่เรียกใช้ดังนั้นบรรทัดที่สองทั้งหมดจะสืบทอดไฟล์ descriptor สี่และคำสั่งผสมตามด้วย3>&1จะสืบทอดสืบทอด descriptor ไฟล์สาม ดังนั้นการ4>&-ทำให้แน่ใจว่าคำสั่งผสมภายในจะไม่สืบทอดไฟล์ descriptor สี่และ3>&-จะไม่สืบทอดไฟล์ descriptor สามดังนั้น command1 รับ 'สะอาด' สภาพแวดล้อมมาตรฐานที่มากกว่า คุณสามารถเลื่อนด้านใน4>&-ข้างๆ3>&-แต่ฉันคิดว่าทำไมไม่ จำกัด ขอบเขตเท่าที่จะทำได้

ฉันไม่แน่ใจว่าบ่อยครั้งที่สิ่งต่าง ๆ ใช้ file descriptor สามหรือสี่โดยตรง - ฉันคิดว่าโปรแกรมส่วนใหญ่ใช้ syscalls ที่ส่งคืนไฟล์ descriptor ที่ไม่ได้ใช้ที่ไม่ได้ใช้แล้ว แต่บางครั้งโค้ดเขียนไปยัง file descriptor 3 โดยตรงฉัน เดา (ฉันนึกภาพออกว่าโปรแกรมกำลังตรวจสอบ file descriptor เพื่อดูว่ามันเปิดอยู่หรือไม่และใช้มันถ้ามันเป็นหรือทำงานต่างไปตามนั้นถ้าไม่ใช่) ดังนั้นสิ่งหลังน่าจะดีที่สุดที่คุณควรคำนึงถึงและใช้สำหรับกรณีทั่วไป


คำอธิบายที่ดี!
selurvedu

6

ใน Ubuntu และ Debian apt-get install moreutilsคุณสามารถ สิ่งนี้มียูทิลิตีที่เรียกmispipeว่าคืนสถานะการออกของคำสั่งแรกในไพพ์


5
(command | tee out.txt; exit ${PIPESTATUS[0]})

ต่างจากคำตอบของ @ cODAR ซึ่งจะส่งคืนรหัสทางออกดั้งเดิมของคำสั่งแรกและไม่เพียง 0 สำหรับความสำเร็จและ 127 สำหรับความล้มเหลว แต่เป็น @Chaoran ${PIPESTATUS[0]}ชี้ให้เห็นคุณก็สามารถโทร มันเป็นสิ่งสำคัญ แต่สิ่งที่ใส่ไว้ในวงเล็บ


4

นอกเหนือจากการทุบตีคุณสามารถทำได้:

bash -o pipefail  -c "command1 | tee output"

/bin/shนี้จะเป็นประโยชน์สำหรับตัวอย่างเช่นในสคริปต์นินจาที่เปลือกคาดว่าจะเป็น


3

PIPESTATUS [@] จะต้องคัดลอกไปยังอาร์เรย์ทันทีหลังจากคำสั่งไพพ์ส่งคืน การอ่าน PIPESTATUS [@] ใด ๆจะลบเนื้อหา คัดลอกไปยังอาเรย์อื่นถ้าคุณวางแผนที่จะตรวจสอบสถานะของคำสั่งไพพ์ทั้งหมด "$?" เป็นค่าเดียวกับองค์ประกอบสุดท้ายของ "$ {PIPESTATUS [@]}" และการอ่านดูเหมือนว่าจะทำลาย "$ {PIPESTATUS [@]}" แต่ฉันไม่ได้ยืนยันเรื่องนี้อย่างแน่นอน

declare -a PSA  
cmd1 | cmd2 | cmd3  
PSA=( "${PIPESTATUS[@]}" )

สิ่งนี้จะไม่ทำงานหากไพพ์นั้นอยู่ในเชลล์ย่อย สำหรับวิธีแก้ไขปัญหานั้น
ดูbash pipestatus ในคำสั่ง backticked?


3

วิธีที่ง่ายที่สุดในการทำเช่นนี้ใน bash ธรรมดาคือการใช้การทดแทนกระบวนการแทนไพพ์ไลน์ มีความแตกต่างหลายประการ แต่อาจไม่สำคัญมากสำหรับกรณีการใช้งานของคุณ:

  • เมื่อรันไปป์ไลน์ bash จะรอจนกว่ากระบวนการทั้งหมดจะเสร็จสมบูรณ์
  • การส่ง Ctrl-C เพื่อทุบตีทำให้มันฆ่ากระบวนการทั้งหมดของไปป์ไลน์ไม่ใช่เฉพาะกระบวนการหลัก
  • pipefailตัวเลือกและPIPESTATUSตัวแปรไม่เกี่ยวข้องกับขั้นตอนการเปลี่ยนตัว
  • อาจเป็นไปได้มากขึ้น

jobsด้วยกระบวนการทดแทนทุบตีเพียงแค่เริ่มต้นกระบวนการและลืมเกี่ยวกับมันก็ไม่ได้แม้ในที่มองเห็นได้

กล่าวถึงความแตกต่างกันconsumer < <(producer)และproducer | consumerเทียบเท่าโดยพื้นฐานแล้ว

หากคุณต้องการที่จะพลิกเป็นที่หนึ่งที่กระบวนการ "หลัก" producer > >(consumer)คุณเพียงแค่พลิกคำสั่งและทิศทางของการทดแทนไป ในกรณีของคุณ:

command > >(tee out.txt)

ตัวอย่าง:

$ { echo "hello world"; false; } > >(tee out.txt)
hello world
$ echo $?
1
$ cat out.txt
hello world

$ echo "hello world" > >(tee out.txt)
hello world
$ echo $?
0
$ cat out.txt
hello world

อย่างที่ฉันพูดมีความแตกต่างจากนิพจน์ท่อ กระบวนการอาจไม่หยุดทำงานเว้นแต่จะมีความไวต่อการปิดท่อ โดยเฉพาะอย่างยิ่งมันอาจเขียนสิ่งต่าง ๆ ไปยัง stdout ของคุณซึ่งอาจทำให้สับสน


1

วิธีการแก้ปัญหาเปลือกบริสุทธิ์:

% rm -f error.flag; echo hello world \
| (cat || echo "First command failed: $?" >> error.flag) \
| (cat || echo "Second command failed: $?" >> error.flag) \
| (cat || echo "Third command failed: $?" >> error.flag) \
; test -s error.flag  && (echo Some command failed: ; cat error.flag)
hello world

และตอนนี้ที่สองcatถูกแทนที่ด้วยfalse:

% rm -f error.flag; echo hello world \
| (cat || echo "First command failed: $?" >> error.flag) \
| (false || echo "Second command failed: $?" >> error.flag) \
| (cat || echo "Third command failed: $?" >> error.flag) \
; test -s error.flag  && (echo Some command failed: ; cat error.flag)
Some command failed:
Second command failed: 1
First command failed: 141

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

เมธอดนี้อนุญาตให้ดักจับ stdout และ stderr สำหรับแต่ละคำสั่งดังนั้นคุณสามารถดัมพ์นั้นเช่นกันในล็อกไฟล์หากมีข้อผิดพลาดเกิดขึ้นหรือเพียงแค่ลบมันหากไม่มีข้อผิดพลาด (เช่นเอาต์พุตของ dd)


1

ตั้งอยู่บนคำตอบของ @ brian-s-wilson; ฟังก์ชันผู้ช่วย bash นี้:

pipestatus() {
  local S=("${PIPESTATUS[@]}")

  if test -n "$*"
  then test "$*" = "${S[*]}"
  else ! [[ "${S[@]}" =~ [^0\ ] ]]
  fi
}

ใช้แล้ว:

1: get_bad_things ต้องประสบความสำเร็จ แต่ไม่ควรสร้างผลลัพธ์ แต่เราต้องการเห็นผลลัพธ์ที่ผลิตออกมา

get_bad_things | grep '^'
pipeinfo 0 1 || return

2: ไปป์ไลน์ทั้งหมดต้องสำเร็จ

thing | something -q | thingy
pipeinfo || return

1

บางครั้งมันอาจจะง่ายและชัดเจนกว่าในการใช้คำสั่งภายนอกแทนที่จะขุดลงไปในรายละเอียดของ bash ไปป์ไลน์จากการประมวลผลภาษาสคริปต์ขั้นต่ำสุดออกมาพร้อมกับโค้ดส่งคืนของคำสั่งที่สอง * เหมือนไปป์ไลน์ แต่ต่างจากที่อนุญาตให้ย้อนกลับทิศทางของไพพ์เพื่อให้เราสามารถจับโค้ดส่งคืนของผู้ผลิตได้ กระบวนการ (ด้านล่างคือทั้งหมดในบรรทัดคำสั่ง แต่มีการติดตั้ง):shshshexecline

$ # using the full execline grammar with the execlineb parser:
$ execlineb -c 'pipeline { echo "hello world" } tee out.txt'
hello world
$ cat out.txt
hello world

$ # for these simple examples, one can forego the parser and just use "" as a separator
$ # traditional order
$ pipeline echo "hello world" "" tee out.txt 
hello world

$ # "write" order (second command writes rather than reads)
$ pipeline -w tee out.txt "" echo "hello world"
hello world

$ # pipeline execs into the second command, so that's the RC we get
$ pipeline -w tee out.txt "" false; echo $?
1

$ pipeline -w tee out.txt "" true; echo $?
0

$ # output and exit status
$ pipeline -w tee out.txt "" sh -c "echo 'hello world'; exit 42"; echo "RC: $?"
hello world
RC: 42
$ cat out.txt
hello world

ใช้pipelineมีความแตกต่างเดียวกันกับท่อทุบตีพื้นเมืองทดแทนกระบวนการทุบตีที่ใช้ในการตอบ# 43972501

* จริงๆแล้วpipelineไม่ได้ออกเลยเว้นแต่ว่ามีข้อผิดพลาด มันรันในคำสั่งที่สองดังนั้นมันเป็นคำสั่งที่สองที่จะกลับมา

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.