อะไรคือสิ่งที่เทียบเท่ากับ zsh ของ bash's export -f


24

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

สิ่งที่ผมชอบมากที่สุดคือข้อเท็จจริงที่ว่าzshคือ .bashrc'เข้ากันได้กับทุกฟังก์ชั่นที่ผมกำหนดไว้ในของฉัน

หนึ่งจับแม้ว่า ฟังก์ชั่นทำงานได้อย่างสมบูรณ์แบบ แต่ฉันไม่สามารถเข้าใจได้ว่าระบบส่งออกทำงานอย่างไร

ฉันได้บางส่วนของผู้ฟังก์ชั่นการส่งออกเพื่อที่ฉันจะใช้พวกเขาที่อื่นเช่นในสคริปต์และโปรแกรมภายนอกด้วย.bashrcexport -f

ใน zsh การส่งออกดูเหมือนจะไม่ได้พูดคุยด้วยซ้ำ การโหลดอัตโนมัติหรือไม่ สองสิ่งนั้นเหมือนกันหรือไม่ ฉันมีเวลายากที่จะหามัน


2
นี่เป็นคำถามที่เก่ามาก แต่ฉันอยากจะบอกว่า "ไดเรกทอรีการทำงานปัจจุบันและบรรทัดคำสั่งที่แท้จริงอยู่ในบรรทัดที่แตกต่างกัน" ไม่มีอะไรเกี่ยวข้องกับ zsh ขึ้นอยู่กับว่าคุณตั้งค่าพรอมต์ของคุณแค่ไหน
4ae1e1

คำตอบ:


11

ตัวแปรสภาพแวดล้อมที่มีฟังก์ชั่นเป็นแฮ็คทุบตี Zsh ไม่มีอะไรคล้ายกัน คุณสามารถทำสิ่งที่คล้ายกับรหัสไม่กี่บรรทัด ตัวแปรสภาพแวดล้อมมีสตริง รุ่นเก่าของทุบตีก่อนทำพิษถูกค้นพบที่เก็บไว้รหัสฟังก์ชั่นในตัวแปรที่มีชื่อเป็นที่ของฟังก์ชั่นและมีค่าตามด้วยรหัสของฟังก์ชั่นตามด้วย() { }คุณสามารถใช้รหัสต่อไปนี้เพื่อนำเข้าตัวแปรด้วยการเข้ารหัสนี้และพยายามเรียกใช้พวกเขาด้วยการตั้งค่าเหมือนทุบตี โปรดทราบว่า zsh ไม่สามารถเลียนแบบคุณลักษณะทุบตีทั้งหมดสิ่งที่คุณทำได้คือเข้าใกล้นิดหน่อย (เช่นเพื่อ$fooแยกค่าและขยายอักขระตัวแทนและสร้างอาร์เรย์แบบ 0)

bash_function_preamble='
    emulate -LR ksh
'
for name in ${(k)parameters}; do
  [[ "-$parameters[name]-" = *-export-* ]] || continue
  [[ ${(P)name} = '() {'*'}' ]] || continue
  ((! $+builtins[$name])) || continue
  functions[$name]=$bash_function_preamble${${${(P)name}#"() {"}%"}"}
done

(ดังที่Stéphane Chazelasผู้ค้นพบต้นฉบับของ Shellshock กล่าวว่ารุ่นก่อนหน้าของคำตอบนี้สามารถเรียกใช้รหัสโดยอำเภอใจได้ณ จุดนี้หากคำจำกัดความของฟังก์ชั่นผิดรูปแบบรุ่นนี้ไม่ แต่แน่นอนทันทีที่คุณดำเนินการคำสั่งใด ๆ มันอาจเป็นฟังก์ชั่นที่นำเข้าจากสภาพแวดล้อม)

ฟังก์ชันการเข้ารหัส bash รุ่นหลัง Shellshock ในสภาพแวดล้อมโดยใช้ชื่อตัวแปรที่ไม่ถูกต้อง (เช่นBASH_FUNC_myfunc%%) สิ่งนี้ทำให้ยากต่อการแยกวิเคราะห์ที่เชื่อถือได้เนื่องจาก zsh ไม่ได้จัดเตรียมอินเทอร์เฟซเพื่อแยกชื่อตัวแปรดังกล่าวจากสภาพแวดล้อม

ฉันไม่แนะนำให้ทำเช่นนี้ การใช้ฟังก์ชันที่เอ็กซ์พอร์ตในสคริปต์เป็นความคิดที่ไม่ดี: มันสร้างการพึ่งพาที่มองไม่เห็นในสคริปต์ หากคุณเคยเรียกใช้สคริปต์ของคุณในสภาพแวดล้อมที่ไม่มีฟังก์ชั่นของคุณ (ในเครื่องอื่นในงาน cron หลังจากเปลี่ยนไฟล์การเริ่มต้นเชลล์ของคุณ ... ) สคริปต์ของคุณจะไม่ทำงานอีกต่อไป ให้จัดเก็บฟังก์ชันทั้งหมดของคุณไว้ในไฟล์ที่แยกต่างหากอย่างน้อยหนึ่งไฟล์ (เช่น~/lib/shell/foo.sh) และเริ่มสคริปต์ของคุณโดยการนำเข้าฟังก์ชั่นที่ใช้ ( . ~/lib/shell/foo.sh) วิธีนี้หากคุณปรับเปลี่ยนfoo.shคุณสามารถค้นหาสคริปต์ที่ต้องการได้อย่างง่ายดาย หากคุณคัดลอกสคริปต์คุณสามารถค้นหาไฟล์เสริมที่ต้องการได้อย่างง่ายดาย

Zsh (และ ksh ก่อนหน้า) ทำให้สะดวกยิ่งขึ้นด้วยการจัดเตรียมวิธีการโหลดฟังก์ชันในสคริปต์ที่ใช้งานโดยอัตโนมัติ ข้อ จำกัด คือคุณสามารถใส่ได้เพียงหนึ่งฟังก์ชันต่อไฟล์ ประกาศฟังก์ชันเป็น autoloaded และวางนิยามฟังก์ชันในไฟล์ที่มีชื่อคือชื่อของฟังก์ชัน ใส่ไฟล์นี้ในไดเรกทอรีที่ระบุไว้$fpath(ซึ่งคุณสามารถกำหนดค่าผ่านFPATHตัวแปรสภาพแวดล้อม) ในสคริปต์ของคุณประกาศฟังก์ชัน autoloaded autoload -U fooกับ

นอกจากนี้ zsh สามารถรวบรวมสคริปต์เพื่อประหยัดเวลาในการแยกวิเคราะห์ โทรzcompileเพื่อรวบรวมสคริปต์ สิ่งนี้จะสร้างไฟล์ที่มี.zwcนามสกุล หากไฟล์นี้มีอยู่แล้วautoloadจะโหลดไฟล์ที่คอมไพล์แทนรหัสแหล่งที่มา คุณสามารถใช้zrecompileฟังก์ชันเพื่อคอมไพล์นิยามฟังก์ชันทั้งหมดในไดเรกทอรี


1
ตลกว่ารหัสของคุณมีช่องโหว่ ShellShock เดียวกันbashได้ (ไม่ได้ตรวจสอบว่าเนื้อหาของตัวแปรที่เป็นเพียงความหมายที่ฟังก์ชั่นและกระบวนการชื่อตัวแปรใด ๆ เช่นHTTP_HOSTหรือLC_X) คำตอบที่ดีเป็นอย่างอื่น
Stéphane Chazelas

@ StéphaneChazelasหากคุณจะเรียกใช้คำสั่งด้วยฟังก์ชั่นที่นำเข้าจากสภาพแวดล้อมที่คุณหายไปสวยมาก แต่ฉันได้อัปเดตรหัสการนำเข้าเพื่อไม่ให้ใช้รหัสโดยอำเภอใจ มันไม่ได้มีประโยชน์มากนักเนื่องจาก bash post-shellshock ไม่ได้เข้ารหัสฟังก์ชั่นที่ส่งออกด้วยวิธีเดียวกัน
Gilles 'SO- หยุดความชั่วร้าย'

ตอนนี้คุณได้แก้ไขค่าเทียบเท่า CVE-2014-6271 แต่ยังคงมีช่องโหว่หลายประเภทของ CVE-2014-6277 / 6278 ... เนื่องจากคุณยังคงเปิดเผย zsh parser ให้ใช้รหัสในตัวแปรใด ๆ รวมถึงบางอย่างที่อาจอยู่ภายใต้การควบคุมของผู้โจมตีในบางบริบท (เนื่องจากโค้ดในzsh -c 'functions[f]=$VAR' ถูกวิเคราะห์คำแม้ว่าfจะไม่เรียกใช้ฟังก์ชัน) วิธีการแก้ไขคือพิจารณาเฉพาะตัวแปรที่มีชื่อตามเทมเพลตที่สงวนไว้เช่นนั้น$BASH_FUNC_x%%แต่อย่างที่คุณพูดzshไม่มี API ที่จะแสดงรายการหรือดึงข้อมูลเหล่านั้น คุณจะต้องโทรperlหาตัวอย่าง
Stéphane Chazelas

7

หากคุณใส่การประกาศฟังก์ชั่นของคุณใน. zshenvฟังก์ชั่นของคุณจะสามารถใช้งานได้จากสคริปต์โดยไม่ต้องใช้ความพยายามใด ๆ


ทำไมคุณถึงลงคะแนนคำตอบของฉัน กรุณาอธิบาย.
rools

ยังคงรอคำตอบและยังทำงานอยู่!
rools

ฉันเพิ่งค้นพบคำตอบนี้และมันเป็นทางออกที่ดี
AFH

ฉันไม่ได้ลงคะแนนเลย และ TBH ผู้ปฏิบัติการกำลังถามเกี่ยวกับการส่งออกข้อมูลจาก. bashrc ซึ่งเป็นความคิดที่ไม่ดีควรวางไว้ในสคริปต์เพื่อให้คุณไม่ต้องเจอกับสภาพแวดล้อมที่ยิ่งใหญ่ แต่วิธีการแก้ปัญหาของคุณเป็นเพียงแค่ความแตกต่างของแนวคิดที่ไม่ดีนั้นให้ใส่สคริปต์ของคุณทั้งหมด.zshenvและจะทำให้การเรียกใช้ zsh ช้าลงโดยการแยกโค้ดจำนวนมากที่ไม่เคยใช้ นอกจากนี้มันไม่เหมือนกับการส่งออกฟังก์ชั่นเช่นเดียวกับตัวแปรที่ส่งออกฟังก์ชั่นที่ส่งออกจะใช้ได้เฉพาะกับกระบวนการลูก ในขณะที่ทุกสิ่งที่คุณใส่.zshenvมีให้ทุก zsh
Metamorphic

ในที่สุดหากคุณพึ่งพารหัสส่วนบุคคลที่คุณใส่ไว้.zshenvสคริปต์ของคุณทั้งหมดจะไม่สามารถพกพาได้ทั้งหมด โดยปกติสคริปต์อาจขึ้นอยู่กับแต่ละอื่น ๆ ซึ่งเป็นเรื่องปกติคุณสามารถแจกจ่ายให้กัน แต่ถ้าพวกเขาขึ้นอยู่กับการมีฟังก์ชั่นพิเศษใน.zshenvไม่มีใครจะต้องการใช้พวกเขาหรือพวกเขาจะต้องถูกเรียกด้วยพิเศษZDOTDIRเพื่อป้องกันคุณ.zshenvจากการถูกดำเนินการ มันจะเจ็บปวด
Metamorphic
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.