ทำไม GNU ไม่ทำงานแบบขนานกับ“ bash -c”


9
% echo -e '1\n2' | parallel "bash -c 'echo :\$1' '' {}"
:1
:2
% echo -e '1\n2' | parallel bash -c 'echo :\$1' '' {}


%

ฉันคาดหวังว่าบรรทัดที่สองจะทำหน้าที่เดียวกัน

คำตอบ:


11

parallelรันคำสั่งในเปลือกที่มีอยู่แล้ว (ซึ่งเปลือกมันจะถูกกำหนดโดยparallelใช้การวิเคราะห์พฤติกรรม (ความตั้งใจที่จะก่อให้เกิดการเป็นเปลือกเช่นเดียวกับคนที่parallelถูกเรียกจาก ). คุณสามารถตั้งค่า$PARALLEL_SHELLตัวแปรในการแก้ไขปัญหาเปลือก)

มันไม่ใช่คำสั่งที่คุณส่งให้parallelเหมือนอย่างที่คุณต้องการสำหรับenvหรือxargsคำสั่ง แต่เป็นบรรทัดคำสั่งเชลล์ (เช่นเดียวกับที่คุณทำกับevalคำสั่ง)

เหมือนevalในparallel arg1 arg2, parallelมีการเชื่อมโยงข้อโต้แย้งที่มีช่องว่างในระหว่าง (ดังนั้นมันจะกลายเป็นarg1 arg2) <the-shell> -cและสตริงที่ถูกส่งไปยัง

สำหรับข้อโต้แย้งที่ถูกส่งผ่านparallelstdin ให้parallelอ้างอิงคำพูดในรูปแบบที่เชลล์คาดหวังไว้ (เป็นงานที่ยากและมีข้อผิดพลาดซึ่งเป็นสาเหตุที่คุณจะพบว่ามีข้อบกพร่องมากมายที่แก้ไขรอบ ๆ ในparallelรายการของการเปลี่ยนแปลง () บางส่วนยังไม่ได้รับการแก้ไขตั้งแต่วันที่ 2017-03-06)) และผนวกเข้ากับบรรทัดคำสั่งนั้น

ดังนั้นสำหรับตัวอย่างเช่นถ้าเรียกจากภายในbash,

echo "foo'bar" | parallel echo foo

จะมีการเรียกแบบขนานbash -cพร้อมกับecho foo foo\'barเป็นบรรทัดคำสั่ง และถ้าเรียกจากภายในrc(หรือPARALLEL_SHELL=rc) ด้วยrc -cecho foo foo''''bar

ใน:

parallel bash -c 'echo :\$1' '' {}

parallel เชื่อมข้อขัดแย้งที่ให้:

bash -c echo :$1  {}

และด้วยการ{}ขยายและยกมาในรูปแบบที่เหมาะสมสำหรับเชลล์ที่คุณโทรหาparallelส่งผ่านสิ่ง<that-shell> -cที่จะเรียกbash -c echoด้วย:$1ใน$0และอาร์กิวเมนต์ปัจจุบัน$1มา

มันไม่parallelทำงาน ที่นี่คุณอาจต้องการ:

printf '1\n2\n' | PARALLEL_SHELL=bash parallel 'echo :{}'

เพื่อดูว่ามีอะไรparallelคุณสามารถเรียกใช้ภายใต้strace -fe execve(หรือเทียบเท่าในระบบของคุณถ้าไม่ Linux)

ที่นี่คุณสามารถใช้ GNU xargsแทนparallelการประมวลผลที่ง่ายขึ้นใกล้กับสิ่งที่คุณคาดหวัง:

printf '1\n2\n' | xargs -rn1 -P4 bash -c 'echo ":$1"' ''

ดูการอภิปรายได้ที่https://lists.gnu.org/archive/html/bug-parallel/2015-05/msg00005.html

โปรดทราบว่าbash -c 'echo foo' '' fooคุณกำลังสร้าง$0สตริงที่ว่างเปล่าสำหรับสคริปต์แบบอินไลน์ ฉันจะหลีกเลี่ยงสิ่งนั้นเช่นเดียวกับที่$0ใช้ในข้อความแสดงข้อผิดพลาด เปรียบเทียบ:

$ bash -c 'echo x > "$1"' '' /
: /: Is a directory

กับ

$ bash -c 'echo x > "$1"' bash /
bash: /: Is a directory

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


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