คนที่สามารถให้คู่ของตัวอย่างเกี่ยวกับวิธีการใช้coproc
?
คนที่สามารถให้คู่ของตัวอย่างเกี่ยวกับวิธีการใช้coproc
?
คำตอบ:
กระบวนการร่วมเป็นksh
คุณลักษณะ (มีอยู่แล้วksh88
) zsh
มีคุณลักษณะตั้งแต่เริ่มต้น (ต้น 90 ต้น) ในขณะที่เพิ่งเพิ่มเข้ามาbash
ใน4.0
(2009)
อย่างไรก็ตามพฤติกรรมและส่วนต่อประสานนั้นแตกต่างกันอย่างมากระหว่าง 3 shells
แนวคิดนี้เหมือนกันแม้ว่ามันจะช่วยให้สามารถเริ่มงานในพื้นหลังและสามารถส่งอินพุตและอ่านเอาต์พุตโดยไม่ต้องหันไปใช้ท่อที่มีชื่อ
ทำด้วยไพพ์ที่ไม่มีชื่อซึ่งมีเชลล์และซ็อกเก็ตแพร์ส่วนใหญ่ที่มี ksh93 รุ่นล่าสุดในบางระบบ
ในa | cmd | b
, a
ฟีดข้อมูลcmd
และb
อ่านเอาท์พุท เล่นcmd
ในฐานะผู้ร่วมกระบวนการช่วยให้เปลือกเป็นทั้งและa
b
ในksh
คุณเริ่ม coprocess เป็น:
cmd |&
คุณป้อนข้อมูลcmd
ด้วยการทำสิ่งต่าง ๆ เช่น:
echo test >&p
หรือ
print -p test
และอ่านcmd
ผลลัพธ์ด้วยสิ่งต่าง ๆ เช่น:
read var <&p
หรือ
read -p var
cmd
จะเริ่มต้นเป็นงานพื้นหลังใด ๆ คุณสามารถใช้fg
, bg
, kill
เกี่ยวกับมันและดูมันด้วยหรือผ่านทาง%job-number
$!
หากต้องการปิดปลายการเขียนของไปป์cmd
อ่านจากคุณสามารถทำได้:
exec 3>&p 3>&-
และเพื่อปิดส่วนท้ายของการอ่านของไพพ์อื่น ๆ (อันที่หนึ่งcmd
เขียนถึง):
exec 3<&p 3<&-
คุณไม่สามารถเริ่มต้นกระบวนการร่วมที่สองเว้นแต่ว่าคุณจะบันทึกไฟล์ไปป์อธิบายไปยัง fds อื่น ๆ ก่อน ตัวอย่างเช่น
tr a b |&
exec 3>&p 4<&p
tr b c |&
echo aaa >&3
echo bbb >&p
ในผู้ร่วมกระบวนการเกือบจะเหมือนกันกับผู้ที่อยู่ในzsh
ksh
ข้อแตกต่างที่แท้จริงคือzsh
กระบวนการร่วมเริ่มต้นด้วยcoproc
คำหลัก
coproc cmd
echo test >&p
read var <&p
print -p test
read -p var
การทำ:
exec 3>&p
หมายเหตุ: สิ่งนี้จะไม่ย้ายcoproc
ไฟล์ descriptor ไปยัง fd 3
(เหมือนในksh
) แต่ทำซ้ำ ดังนั้นไม่มีทางที่ชัดเจนที่จะปิดการให้อาหารหรือการอ่านท่ออื่น ๆ เริ่มต้นอีก coproc
ตัวอย่างเช่นหากต้องการปิดท้ายการให้อาหาร:
coproc tr a b
echo aaaa >&p # send some data
exec 4<&p # preserve the reading end on fd 4
coproc : # start a new short-lived coproc (runs the null command)
cat <&4 # read the output of the first coproc
นอกเหนือไปจากท่อร่วมตามกระบวนการ, zsh
(ตั้งแต่ 3.1.6-dev19 การปล่อยตัวในปี 2000) มีโครงสร้างหลอก TTY expect
ตามชอบ ในการโต้ตอบกับโปรแกรมส่วนใหญ่กระบวนการร่วมแบบ ksh จะไม่ทำงานเนื่องจากโปรแกรมเริ่มบัฟเฟอร์เมื่อเอาต์พุตของพวกเขาเป็นไพพ์
นี่คือตัวอย่างบางส่วน.
เริ่มกระบวนการร่วมx
:
zmodload zsh/zpty
zpty x cmd
(ที่นี่cmd
เป็นคำสั่งง่ายๆ แต่คุณสามารถทำสิ่งต่าง ๆ ด้วยeval
หรือฟังก์ชั่นนักเล่นได้)
ฟีดข้อมูลร่วมกระบวนการ:
zpty -w x some data
อ่านข้อมูลร่วมกระบวนการ (ในกรณีที่ง่ายที่สุด):
zpty -r x var
เช่นเดียวกับexpect
มันสามารถรอผลลัพธ์บางส่วนจากกระบวนการร่วมที่ตรงกับรูปแบบที่กำหนด
ไวยากรณ์ของ bash นั้นใหม่กว่ามากและสร้างขึ้นจากคุณลักษณะใหม่ที่เพิ่งเพิ่มเข้าไปใน ksh93, bash และ zsh มันมีไวยากรณ์เพื่ออนุญาตการจัดการของ file descriptor ที่จัดสรรแบบไดนามิกสูงกว่า 10
bash
มีพื้นฐาน coproc
ไวยากรณ์และขยายหนึ่ง
ไวยากรณ์พื้นฐานสำหรับการเริ่มต้นร่วมกระบวนการดูเหมือนzsh
's:
coproc cmd
ในksh
หรือzsh
ท่อไปและกลับจากร่วมกระบวนการมีการเข้าถึงด้วยและ>&p
<&p
แต่ในbash
ไฟล์ descriptors ของไปป์จากกระบวนการร่วมและไปป์อื่น ๆ ไปยัง co-proccess จะถูกส่งกลับใน$COPROC
อาร์เรย์ (ตามลำดับ${COPROC[0]}
และ${COPROC[1]}
ดังนั้น ...
ฟีดข้อมูลไปยังกระบวนการร่วม:
echo xxx >&"${COPROC[1]}"
อ่านข้อมูลจากกระบวนการร่วม:
read var <&"${COPROC[0]}"
ด้วยไวยากรณ์พื้นฐานคุณสามารถเริ่มต้นกระบวนการร่วมได้ครั้งละหนึ่งกระบวนการเท่านั้น
ในไวยากรณ์เพิ่มเติมคุณสามารถตั้งชื่อกระบวนการร่วมของคุณ (เช่นในzsh
zpty co-proccesses):
coproc mycoproc { cmd; }
คำสั่งที่มีจะเป็นคำสั่งผสม (สังเกตว่าตัวอย่างด้านบนทำให้ระลึกถึงfunction f { ...; }
)
เวลานี้อธิบายไฟล์ที่อยู่ในและ${mycoproc[0]}
${mycoproc[1]}
คุณสามารถเริ่มต้นกระบวนการร่วมได้มากกว่าหนึ่งกระบวนการในแต่ละครั้ง แต่คุณจะได้รับคำเตือนเมื่อคุณเริ่มกระบวนการร่วมในขณะที่ยังทำงานอยู่ (แม้อยู่ในโหมดไม่โต้ตอบ)
คุณสามารถปิดไฟล์ descriptors เมื่อใช้ไวยากรณ์เพิ่มเติม
coproc tr { tr a b; }
echo aaa >&"${tr[1]}"
exec {tr[1]}>&-
cat <&"${tr[0]}"
โปรดทราบว่าการปิดวิธีนี้จะไม่ทำงานในเวอร์ชันทุบตีก่อนหน้า 4.3 ซึ่งคุณต้องเขียนแทน:
fd=${tr[1]}
exec {fd}>&-
เช่นเดียวกับในksh
และzsh
คำอธิบายไฟล์ไปป์เหล่านั้นจะถูกทำเครื่องหมายเป็น close-on-exec
แต่ในbash
วิธีเดียวที่จะผ่านเหล่านั้นไปยังคำสั่งดำเนินการคือการทำซ้ำพวกเขาที่จะ FDS 0
, หรือ1
2
ที่ จำกัด จำนวนกระบวนการร่วมที่คุณสามารถโต้ตอบด้วยสำหรับคำสั่งเดียว (ดูตัวอย่างด้านล่าง)
yash
ไม่ได้มีคุณสมบัติร่วมกระบวนการต่อ se แต่แนวคิดเดียวกันสามารถดำเนินการกับของท่อและกระบวนการคุณสมบัติการเปลี่ยนเส้นทาง yash
มีส่วนต่อประสานกับการpipe()
เรียกของระบบดังนั้นสิ่งนี้สามารถทำได้ค่อนข้างง่ายด้วยมือที่นั่น
คุณจะเริ่มต้นกระบวนการร่วมกับ:
exec 5>>|4 3>(cmd >&5 4<&- 5>&-) 5>&-
สิ่งแรกที่สร้างpipe(4,5)
(5 ปลายการเขียน 4 ส่วนปลายอ่าน) จากนั้นเปลี่ยนเส้นทาง fd 3 ไปยังไพพ์ไปยังกระบวนการที่ทำงานด้วย stdin ที่ปลายอีกด้านหนึ่งและ stdout จะไปที่ไพพ์ที่สร้างขึ้นก่อนหน้านี้ จากนั้นเราก็ปิดท้ายการเขียนของไพพ์นั้นในแม่ซึ่งเราไม่ต้องการ ตอนนี้ในเปลือกเรามี fd 3 เชื่อมต่อกับ stdin ของ cmd และ fd 4 เชื่อมต่อกับ stdout ของ cmd ด้วยท่อ
โปรดทราบว่าแฟล็ก close-on-exec ไม่ได้ถูกตั้งค่าไว้บนตัวให้คำอธิบายไฟล์เหล่านั้น
ในการดึงข้อมูล:
echo data >&3 4<&-
วิธีอ่านข้อมูล:
read var <&4 3>&-
และคุณสามารถปิด fds ได้ตามปกติ:
exec 3>&- 4<&-
กระบวนการร่วมสามารถนำไปใช้กับท่อที่มีชื่อมาตรฐานได้อย่างง่ายดาย ฉันไม่รู้ว่าเมื่อไหร่ที่มีการเปิดตัวท่อชื่อ แต่เป็นไปได้ว่ามันksh
เกิดขึ้นหลังจากมีกระบวนการร่วม (อาจจะอยู่ในช่วงกลางยุค 80, ksh88 ถูก "ปล่อย" ใน 88 แต่ฉันเชื่อว่าksh
ใช้ภายใน AT&T เมื่อไม่กี่ปีก่อน ที่) ซึ่งจะอธิบายว่าทำไม
cmd |&
echo data >&p
read var <&p
สามารถเขียนด้วย:
mkfifo in out
cmd <in >out &
exec 3> in 4< out
echo data >&3
read var <&4
การโต้ตอบกับสิ่งเหล่านั้นเป็นเรื่องที่ตรงไปตรงมามากขึ้นโดยเฉพาะถ้าคุณต้องการเรียกใช้กระบวนการร่วมมากกว่าหนึ่งกระบวนการ (ดูตัวอย่างด้านล่าง)
ประโยชน์เพียงอย่างเดียวของการใช้coproc
คือคุณไม่ต้องล้างท่อที่มีชื่อหลังการใช้งาน
หอยใช้ท่อในโครงสร้างไม่กี่:
cmd1 | cmd2
,$(cmd)
,<(cmd)
, >(cmd)
.ในนั้นข้อมูลไหลในทิศทางเดียวเท่านั้นระหว่างกระบวนการต่าง ๆ
ด้วยกระบวนการร่วมและการตั้งชื่อไปป์แม้ว่ามันจะง่ายต่อการทำงานในการหยุดชะงัก คุณต้องติดตามว่าคำสั่งใดเปิดไฟล์ descriptor ไว้เพื่อป้องกันไม่ให้คำสั่งเปิดค้างไว้และทำให้กระบวนการยังคงอยู่ การหยุดชะงักอาจเป็นเรื่องยุ่งยากในการตรวจสอบเพราะอาจเกิดขึ้นได้ ตัวอย่างเช่นเฉพาะเมื่อมีการส่งข้อมูลมากเท่าที่เติมหนึ่งไปป์เท่านั้น
expect
สิ่งที่ออกแบบมาวัตถุประสงค์หลักของกระบวนการร่วมคือเพื่อให้เชลล์มีวิธีการโต้ตอบกับคำสั่ง อย่างไรก็ตามมันใช้งานไม่ได้
รูปแบบที่ง่ายที่สุดของการหยุดชะงักที่กล่าวถึงข้างต้นคือ:
tr a b |&
echo a >&p
read var<&p
เนื่องจากเอาต์พุตไม่ได้ไปที่เทอร์มินัลจึงtr
บัฟเฟอร์เอาต์พุต ดังนั้นมันจะไม่แสดงผลใด ๆ จนกว่าจะเห็นจุดสิ้นสุดไฟล์ในstdin
นั้นหรือมีการสะสมบัฟเฟอร์เต็มของข้อมูลเพื่อส่งออก ดังนั้นด้านบนหลังจากเชลล์มีเอาต์พุต a\n
(เพียง 2 ไบต์) read
จะบล็อกไม่สิ้นสุดเนื่องจากtr
กำลังรอให้เชลล์ส่งข้อมูลเพิ่มเติม
กล่าวโดยย่อคือท่อไม่ดีสำหรับการโต้ตอบกับคำสั่ง กระบวนการร่วมสามารถใช้เพื่อโต้ตอบกับคำสั่งที่ไม่บัฟเฟอร์เอาต์พุตหรือคำสั่งที่สามารถบอกได้ว่าไม่บัฟเฟอร์ผลลัพธ์ ตัวอย่างเช่นโดยใช้stdbuf
กับคำสั่งบางอย่างในระบบ GNU หรือ FreeBSD ล่าสุด
นั่นเป็นเหตุผลexpect
หรือzpty
ใช้เทอร์มินัลหลอกแทน expect
เป็นเครื่องมือที่ออกแบบมาสำหรับการโต้ตอบกับคำสั่งและทำได้ดี
กระบวนการร่วมสามารถใช้ในการทำประปาที่ซับซ้อนกว่าท่อเปลือกแบบง่ายๆ
คำตอบ Unix.SE อื่นนั้นมีตัวอย่างของการใช้ coproc
นี่คือตัวอย่างแบบง่าย:ลองนึกภาพว่าคุณต้องการฟังก์ชั่นที่ฟีดสำเนาของคำสั่งไปยัง 3 คำสั่งอื่น ๆ จากนั้นให้เอาท์พุทของ 3 คำสั่งเหล่านั้นมาต่อกัน
ทั้งหมดใช้ท่อ
ตัวอย่างเช่นอาหารการส่งออกของprintf '%s\n' foo bar
ไปtr a b
, sed 's/./&&/g'
และcut -b2-
เพื่อให้ได้สิ่งที่ต้องการ:
foo
bbr
ffoooo
bbaarr
oo
ar
ครั้งแรกมันไม่จำเป็นต้องชัดเจน แต่มีความเป็นไปได้สำหรับการหยุดชะงักที่นั่นและมันจะเริ่มเกิดขึ้นหลังจากข้อมูลเพียงไม่กี่กิโลไบต์
จากนั้นขึ้นอยู่กับเชลล์ของคุณคุณจะพบกับปัญหาที่แตกต่างกันจำนวนหนึ่งซึ่งต้องแก้ไขแตกต่างกัน
ตัวอย่างเช่นด้วยzsh
คุณจะทำกับ:
f() (
coproc tr a b
exec {o1}<&p {i1}>&p
coproc sed 's/./&&/g' {i1}>&- {o1}<&-
exec {o2}<&p {i2}>&p
coproc cut -c2- {i1}>&- {o1}<&- {i2}>&- {o2}<&-
tee /dev/fd/$i1 /dev/fd/$i2 >&p {o1}<&- {o2}<&- &
exec cat /dev/fd/$o1 /dev/fd/$o2 - <&p {i1}>&- {i2}>&-
)
printf '%s\n' foo bar | f
ด้านบน fds ร่วมกระบวนการมีชุดแฟล็ก close-on-exec แต่ไม่ใช่แฟล็กที่ทำซ้ำจากพวกเขา (เหมือนใน{o1}<&p
) ดังนั้นเพื่อหลีกเลี่ยงการหยุดชะงักคุณจะต้องตรวจสอบให้แน่ใจว่าปิดในกระบวนการใด ๆ ที่ไม่ต้องการ
ในทำนองเดียวกันเราต้องใช้ subshell และใช้exec cat
ในท้ายที่สุดเพื่อให้แน่ใจว่าไม่มีกระบวนการเชลล์ที่โกหกเกี่ยวกับการเปิดท่อ
ด้วยksh
(ที่นี่ksh93
) นั่นจะต้องเป็น:
f() (
tr a b |&
exec {o1}<&p {i1}>&p
sed 's/./&&/g' |&
exec {o2}<&p {i2}>&p
cut -c2- |&
exec {o3}<&p {i3}>&p
eval 'tee "/dev/fd/$i1" "/dev/fd/$i2"' >&"$i3" {i1}>&"$i1" {i2}>&"$i2" &
eval 'exec cat "/dev/fd/$o1" "/dev/fd/$o2" -' <&"$o3" {o1}<&"$o1" {o2}<&"$o2"
)
printf '%s\n' foo bar | f
( หมายเหตุ:นั่นจะไม่ทำงานบนระบบที่ksh
ใช้socketpairs
แทนpipes
และ/dev/fd/n
ทำงานได้บน Linux)
ในksh
fds ด้านบน2
ถูกทำเครื่องหมายด้วยแฟล็กclose-on-exec เว้นแต่ว่าพวกเขาจะถูกส่งผ่านอย่างชัดเจนในบรรทัดคำสั่ง นั่นเป็นเหตุผลที่เราไม่จำเป็นต้องปิดตัวอธิบายไฟล์ที่ไม่ได้ใช้เช่น - zsh
แต่มันก็เป็นสาเหตุที่เราต้องทำ{i1}>&$i1
และใช้eval
สำหรับค่าใหม่ของ$i1
, จะถูกส่งผ่านไปtee
และcat
...
ในbash
สิ่งนี้ไม่สามารถทำได้เพราะคุณไม่สามารถหลีกเลี่ยงการตั้งค่าสถานะ close-on-exec
ด้านบนมันค่อนข้างง่ายเพราะเราใช้คำสั่งภายนอกง่าย ๆ เท่านั้น มันซับซ้อนมากขึ้นเมื่อคุณต้องการใช้เชลล์สร้างในนั้นแทนและคุณเริ่มทำงานในเชลล์บั๊ก
เปรียบเทียบด้านบนด้วยการใช้ชื่อ pipes:
f() {
mkfifo p{i,o}{1,2,3}
tr a b < pi1 > po1 &
sed 's/./&&/g' < pi2 > po2 &
cut -c2- < pi3 > po3 &
tee pi{1,2} > pi3 &
cat po{1,2,3}
rm -f p{i,o}{1,2,3}
}
printf '%s\n' foo bar | f
หากคุณต้องการโต้ตอบกับคำสั่งใช้expect
หรือzsh
's zpty
หรือไปป์ที่มีชื่อ
ถ้าคุณต้องการที่จะทำท่อประปาแฟนซีใช้ท่อชื่อ
กระบวนการร่วมสามารถทำสิ่งต่าง ๆ ข้างต้นได้ แต่ต้องเตรียมพร้อมที่จะทำอะไรบางอย่างที่ไม่สำคัญ
exec {tr[1]}>&-
ดูเหมือนจะทำงานกับเวอร์ชันที่ใหม่กว่าและมีการอ้างอิงในรายการ CWRU / changelog ( อนุญาตให้ใช้คำเช่น {array [ind]} เป็นการเปลี่ยนเส้นทางที่ถูกต้อง ... 2012-09-01) exec {tr[1]}<&-
(หรือ>&-
เทียบเท่าที่ถูกต้องมากขึ้นแม้ว่าจะไม่ได้สร้างความแตกต่างเหมือนที่เพิ่งเรียกclose()
ทั้งคู่) ไม่ได้ปิด stroc ของ coproc แต่การเขียนปลายท่อไปที่ coproc นั้น
yash
แล้ว
mkfifo
คือคุณไม่ต้องกังวลเกี่ยวกับสภาพการแข่งขันและความปลอดภัยสำหรับการเข้าถึงท่อ คุณยังต้องกังวลเกี่ยวกับการหยุดชะงักของ Fifo
stdbuf
คำสั่งสามารถช่วยป้องกันบางอย่างได้ ฉันใช้มันภายใต้ Linux และทุบตี อย่างไรก็ตามฉันเชื่อว่า @ StéphaneChazelasนั้นถูกต้องในบทสรุป: ขั้นตอน "การเกาหัว" จบลงสำหรับฉันเมื่อฉันเปลี่ยนกลับไปเป็นท่อที่มีชื่อเท่านั้น
กระบวนการร่วมถูกนำมาใช้ครั้งแรกในภาษาสคริปต์เชลล์กับksh88
เชลล์ (1988) และต่อมาในzsh
บางจุดก่อนปี 1993
ไวยากรณ์ที่จะเปิดตัวร่วมกระบวนการภายใต้ ksh command |&
คือ เริ่มต้นจากนั้นคุณสามารถเขียนให้command
เข้ามาตรฐานด้วยและอ่านออกมาตรฐานด้วยprint -p
read -p
กว่าสองสามทศวรรษต่อมาทุบตีซึ่งขาดคุณสมบัตินี้ในที่สุดก็เปิดตัวมันในรุ่น 4.0 ของมัน น่าเสียดายที่มีการเลือกไวยากรณ์ที่เข้ากันไม่ได้และซับซ้อนกว่า
ภายใต้ bash 4.0 และใหม่กว่าคุณสามารถเปิดใช้กระบวนการร่วมกับcoproc
คำสั่งเช่น:
$ coproc awk '{print $2;fflush();}'
จากนั้นคุณสามารถส่งบางสิ่งไปยังคำสั่ง stdin ด้วยวิธีนี้:
$ echo one two three >&${COPROC[1]}
และอ่านผลลัพธ์ awk ด้วย:
$ read -ru ${COPROC[0]} foo
$ echo $foo
two
ภายใต้ ksh นั่นจะเป็น:
$ awk '{print $2;fflush();}' |&
$ print -p "one two three"
$ read -p foo
$ echo $foo
two
"coproc" คืออะไร?
มันสั้นสำหรับ "กระบวนการร่วม" ซึ่งหมายถึงกระบวนการที่สองร่วมมือกับเชลล์ มันคล้ายกับงานพื้นหลังที่เริ่มต้นด้วย "&" ที่ส่วนท้ายของคำสั่งยกเว้นว่าแทนที่จะใช้อินพุตและเอาต์พุตมาตรฐานร่วมกันเป็นพาเรนต์เชลล์เดียวกันมาตรฐาน I / O มาตรฐานจะเชื่อมต่อกับพาเรนต์เชลล์โดยพิเศษ ชนิดของท่อที่เรียกว่า FIFO สำหรับการอ้างอิงคลิกที่นี่
หนึ่งเริ่ม coproc ใน zsh ด้วย
coproc command
คำสั่งจะต้องมีการเตรียมพร้อมที่จะอ่านจาก stdin และ / หรือเขียนไปยัง stdout หรือไม่ได้ใช้งานมากเท่า coproc
อ่านบทความนี้ที่นี่เป็นกรณีศึกษาระหว่าง exec และ coproc
|
พวกเขากำลังชนิดไม่พิเศษของท่อที่พวกเขามีท่อเดียวกับที่ใช้กับ (นั่นคือใช้ไพพ์ในเชลล์ส่วนใหญ่และซ็อกเก็ตคู่ใน ksh93) ท่อและซ็อกเก็ตคู่เป็นแบบเข้าก่อนออกก่อนพวกเขาทั้งหมด FIFO mkfifo
ทำให้ไปป์ที่มีชื่อตัวประมวลผลร่วมไม่ใช้ไพพ์ที่มีชื่อ
นี่เป็นอีกตัวอย่างที่ดี (และใช้งานได้) - เซิร์ฟเวอร์อย่างง่ายที่เขียนด้วย BASH โปรดทราบว่าคุณต้องใช้ OpenBSD netcat
คลาสสิกจะใช้งานไม่ได้ แน่นอนคุณสามารถใช้ซ็อกเก็ต inet แทน unix หนึ่ง
server.sh
:
#!/usr/bin/env bash
SOCKET=server.sock
PIDFILE=server.pid
(
exec </dev/null
exec >/dev/null
exec 2>/dev/null
coproc SERVER {
exec nc -l -k -U $SOCKET
}
echo $SERVER_PID > $PIDFILE
{
while read ; do
echo "pong $REPLY"
done
} <&${SERVER[0]} >&${SERVER[1]}
rm -f $PIDFILE
rm -f $SOCKET
) &
disown $!
client.sh
:
#!/usr/bin/env bash
SOCKET=server.sock
coproc CLIENT {
exec nc -U $SOCKET
}
{
echo "$@"
read
} <&${CLIENT[0]} >&${CLIENT[1]}
echo $REPLY
การใช้งาน:
$ ./server.sh
$ ./client.sh ping
pong ping
$ ./client.sh 12345
pong 12345
$ kill $(cat server.pid)
$
bash 4.3.11
คุณสามารถปิดตัวอธิบายไฟล์ coproc โดยตรงโดยไม่ต้องใช้ aux ตัวแปร; ในแง่ของตัวอย่างในคำตอบของคุณexec {tr[1]}<&-
ตอนนี้จะทำงาน (เพื่อปิด stdin ของ coproc โปรดทราบว่ารหัสของคุณ (ทางอ้อม) พยายามที่จะปิดการ{tr[1]}
ใช้>&-
แต่{tr[1]}
เป็นstdinของ coproc และจะต้องปิดด้วย<&-
) การแก้ไขต้องมาจากที่ใดที่หนึ่ง4.2.25
ซึ่งยังคงแสดงปัญหาและ4.3.11
ที่ไม่ได้