รวมเอาท์พุทจากสองคำสั่งในทุบตี


81

เป็นไปได้ไหมที่จะรวมเอาท์พุทจากคำสั่งทั้งสองนี้?

node ~/projects/trunk/index.js 
python ~/projects/trunk/run.py run

ไม่มีคำสั่งออกดังนั้นฉันไม่แน่ใจว่าจะทำอย่างไร


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

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

คำตอบ:


108

คุณสามารถรวมสองคำสั่งโดยการจัดกลุ่มมันด้วย{ }:

{ command1 & command2; }

ป่านฉะนี้คุณสามารถเปลี่ยนเส้นทางกลุ่มไปยังไฟล์ (สุดท้าย;ก่อนที่จะ}มีผลบังคับใช้):

{ command1 & command2; } > new_file

หากคุณต้องการแยกSTDOUTและเป็นSTDERRสองไฟล์:

{ command1 & command2; } > STDOUT_file 2> STDERR_file

3
ไม่สำคัญว่าโปรแกรมเหล่านั้นจะไม่เสร็จ 'tail -f' ไม่ได้ "เสร็จสิ้น" อย่างใดอย่างหนึ่ง แต่ยังคงใช้งานได้และรวมเอาท์พุทของทั้งสองโปรแกรม ทำงานได้มากกว่าสองคำสั่งเช่นกัน ^ c เพื่อออกจากการฆ่าเพียงหนึ่งในคำสั่งที่จัดกลุ่ม คุณจะต้องฆ่าอีกฝ่ายด้วยตนเอง
SuperMagic

5
ดูเหมือนว่าคุณจะขาดไป;ก่อนหน้า}นี้มันบังคับ!
Gilles Quenot

2
ถูกเตือน: สิ่งนี้ไม่รักษาทั้งบรรทัด! คุณจะได้ผลลัพธ์ที่ไม่น่าเชื่อถือเนื่องจากเส้นแบ่งออกเป็นส่วน ๆ และปะปนกัน คุณสามารถลองใช้วิธีนี้{ yes {1..20} & yes {1..20}; } | grep -v '^1 2 3'ซึ่งจะไม่พิมพ์อะไรเลยหากเส้นไม่แตก
antak

8
ฉันอยากจะใช้&&แทน&! command1 & command2- สิ่งนี้จะรัน command1 ในพื้นหลังและเริ่ม command2 ทันทีดังนั้นจึงรันทั้งสองคำสั่งในแบบขนานและ messing up output command1 && command2- สิ่งนี้จะรัน command1 (เบื้องหน้า) และจากนั้นหาก command1 ยอมให้รัน command2
DUzun

1
@DUzun OP กล่าวว่าไม่มีคำสั่งออกดังนั้นด้วยวิธีการแก้ปัญหาของคุณคำสั่งที่สองจะไม่ทำงาน
Zoey Hewll

50

โดยทั่วไปแล้วเป็นไปได้ที่จะใช้การแบ่งกลุ่มย่อยหรือการจัดกลุ่มคำสั่งและเปลี่ยนเส้นทางการส่งออกของกลุ่มทั้งหมดในครั้งเดียว

รหัส:

( command1 ; command2 ; command3 ) | cat

{ command1 ; command2 ; command3 ; } > outfile.txt

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

อย่าลืมว่าวงเล็บปิดในการจัดกลุ่มคำสั่ง (และฟังก์ชั่น) จะต้องแยกออกจากเนื้อหาด้วยเครื่องหมายอัฒภาคหรือขึ้นบรรทัดใหม่ นี่เป็นเพราะ"}"จริงๆแล้วคำสั่ง (คำหลัก) ของมันเองและจะต้องได้รับการปฏิบัติเหมือนเป็นหนึ่งเดียว


2
การเปลี่ยนเส้นทางจากใช้( )งานได้ดีเช่นกัน
muru

2
}ไม่ใช่คำสั่งเลย มันเป็นคำที่สงวนไว้ {เดียวกันจะไปสำหรับ { command1;command2;} > outfile.txtฉันมักจะเขียนรายชื่อดังกล่าวเช่นดังนั้น: คุณสามารถเพิ่มช่องว่างหลังเซมิโคลอน แต่ไม่จำเป็น แม้ว่าพื้นที่หลังจากนั้น{ เป็นสิ่งจำเป็น
สัญลักษณ์ตัวแทน

1
ถูกเตือน: สิ่งนี้ไม่รักษาทั้งบรรทัด! คุณจะได้ผลลัพธ์ที่ไม่น่าเชื่อถือเนื่องจากเส้นแบ่งออกเป็นส่วน ๆ และปะปนกัน คุณสามารถลองใช้วิธีนี้( yes {1..20} & yes {1..20}; ) | grep -v '^1 2 3'ซึ่งจะไม่พิมพ์อะไรเลยหากเส้นไม่แตก (H / t ถึง @antak)
Ole Tange

3
บางครั้งคุณต้องการเรียกใช้ command2 ต่อเมื่อ command1 สำเร็จแล้ว:( command1 && command2 && command3 ) | cat
DUzun

ฉันชอบวงเล็บปีกกา()เช่นเดียวกับวงเล็บปีกกา{}มันทำงานเป็นความคืบหน้าพื้นหลังและจากนั้นคุณต้องจัดการกับผลลัพธ์จากที่ ยังท่อไปยังแมว `| cat` เป็นทางเลือกที่ใหม่กว่า `> / dev / stdout`
DarkMukke

2

ฉันลงเอยด้วยการทำสิ่งนี้ข้อเสนอแนะอื่น ๆ ไม่ทำงานเนื่องจากคำสั่งที่ 2 ถูกฆ่าหรือไม่ดำเนินการ

alias app () {
    nohup python ~/projects/trunk/run.py run 1>/tmp/log 2>&1 &
    echo $! > /tmp/api.pid
    nohup node ~/projects/trunk/index.js 1>/tmp/log 2>&1 &
    echo $! > /tmp/client.pid
    tail -f /tmp/log
}

1
หมายเหตุ: นี่อาจทำให้เกิดข้อผิดพลาด I / O หากทั้งสองกระบวนการพยายามเขียนลงไฟล์ "ในเวลาเดียวกัน"
Djizeus

2
สามารถระบุล็อกไฟล์ที่แตกต่างกัน 2 ไฟล์และทำได้tail -f *.logแม้ว่าฉันไม่เคยเห็นนี่เป็นปัญหากับโพรเซสที่ต่างกัน 2 โพรเซสที่เขียนไปยังล็อกไฟล์เดียวกัน
chovy

@chovy: คุณสามารถเขียนปัญหาของคุณเป็นคำถามที่นี่ ... มันมีประโยชน์
Abdennour TOUMI

1
ถูกเตือน: สิ่งนี้ไม่รักษาทั้งบรรทัด! คุณจะได้ผลลัพธ์ที่ไม่น่าเชื่อถือเนื่องจากเส้นแบ่งออกเป็นส่วน ๆ และปะปนกัน คุณสามารถลองสิ่งนี้ด้วย command1 = yes {1..20}command2 = yes {1..20}และไพพ์เอาท์พุทที่รวมกัน| grep -v '^1 2 3'ซึ่งจะไม่พิมพ์สิ่งใดหากบรรทัดไม่ได้ขาด (H / t ถึง @antak)
Ole Tange

ด้านบนของดิสก์ของคุณอาจทำงานเต็มหากจำนวนข้อมูลมีขนาดใหญ่
Ole Tange

2

ลองสิ่งนี้:

paste $(node ~/projects/trunk/index.js) $(python ~/projects/trunk/run.py run) > outputfile

1
'วาง' ทำอะไร
chovy

@chovy ดูที่นี่: techrepublic.com/article/… ไม่แน่ใจว่ามันจะใช้งานได้ในบริบทนี้หรือไม่
FixMaker

ฉันไม่คิดว่าการวางจะเหมาะสมที่นี่เนื่องจากมีความหมายที่จะวางคอลัมน์ไว้ถัดจากแต่ละอื่น ๆ
Bernhard

@Bernhard แน่นอน แต่มันไม่ได้ระบุไว้ใน req's
frogstarr78

@ frogstarr78 ฉันคิดว่ามันไม่น่าเป็นไปได้อย่างมากว่านี่คือสิ่งที่เขาต้องการ แต่คุณพูดถูกมันไม่ได้ระบุ
แบร์นฮาร์ด

1

การแก้ปัญหาส่วนใหญ่จนถึงปัญหาเส้นบางส่วนไม่ดี สมมติว่าโปรแกรมเป็นวินาที:

cmd1() {
    perl -e 'while(1) { print "a"x3000_000,"\n"}'
}
export -f cmd1
cmd2() {
    perl -e 'while(1) { print "b"x3000_000,"\n"}'
}
export -f cmd2

เมื่อเรียกใช้งานแบบขนานคุณต้องการให้เอาต์พุตมีเส้นเต็มของas ตามด้วยเส้นเต็มของbs สิ่งที่คุณไม่ต้องการaและbs ผสมในบรรทัดเดียวกัน ( tr -s abแทนการทำซ้ำas มีเพียงหนึ่งเดียวaดังนั้นจึงเป็นเรื่องง่ายที่จะเห็นสิ่งที่เกิดขึ้น):

# This is bad - half lines are mixed
$ (cmd1 & cmd2 ) | tr -s ab
bababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababa
ababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababab

ถ้าคุณใช้ GNU Parallel แทนคุณจะได้เส้นที่สะอาดและสมบูรณ์ด้วยas หรือbs แต่ไม่ผสมกัน:

$ parallel --line-buffer ::: cmd1 cmd2 | tr -s ab
a
a
b
b
b
b
a

เวอร์ชั่นใหม่ของ GNU Parallel แม้จะหลีกเลี่ยงการเติมดิสก์ของคุณ: ข้างต้นสามารถทำงานได้ตลอดไป


0

เนื่องจากคุณใช้อยู่แล้วnodeคุณอาจต้องการลองพร้อมกัน

เรียกใช้หลายคำสั่งพร้อมกัน ชอบnpm run watch-js & npm run watch-lessแต่ดีกว่า


0

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

(echo 'ab' && echo 'cd' && echo 'ef') | tr -d '\n'
>>> abcdef

เป็นตัวอย่างในโลกแห่งความจริงรหัสด้านล่างจะฝังข้อความ ASCII ระหว่างสองสตริงคงที่ของไบต์ (สร้างคำสั่งการพิมพ์ในกรณีนี้)

#   hex prefix           encode a message as hex    hex suffix    | strip newline | hex to binary | (then, for example, send the binary over a TCP connection)
(echo '1b40' && echo "Test print #1" | xxd -p && echo '1d564103') | tr -d '\n'    | xxd -r -p     | nc -N 192.168.192.168 9100

(หมายเหตุ: วิธีนี้ใช้ได้เฉพาะเมื่อคำสั่งออกจากการรวม stdout จากคำสั่งที่ไม่ออกให้ดูคำตอบอื่น ๆ )


(1) โปรดแสดงเอาต์พุต (ที่คาดไว้) ของคำสั่งที่สองของคุณ (2) โปรดแสดงว่า OP จะใช้เทคนิคนี้เพื่อแก้ปัญหาของเขาอย่างไร
สกอตต์

1) เอาต์พุตของคำสั่งที่สองคือ non-ascii binary ดังนั้นจึงไม่มีประโยชน์ที่จะแสดง 2) OP น่าจะแก้ปัญหาเฉพาะของเขาระหว่างปี 2013 และตอนนี้ ตอนนี้คำถามนี้เป็นการอ้างอิงที่มีประสิทธิภาพเกี่ยวกับการรวม stdout ของคำสั่ง Bash หลายคำสั่งดังนั้นฉันเชื่อว่าเทคนิคสำหรับการรวมพวกเขาในหนึ่งบรรทัดเป็น "สูตรอาหาร" ที่มีประโยชน์ที่จะกล่าวถึงที่นี่ (ตั้งแต่ฉันมาที่นี่ มัน).
ลุค
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.