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


13

ฉันใช้โมดูลเพื่อควบคุมแพ็คเกจบนระบบของฉันและฉันได้python/2.7.2ติดตั้งเป็นโมดูล ฉันมีปฏิบัติการหลามง่ายpython_exe.pyที่ฉันจะโทรจากง่าย 'ขับรถ' runit.shสคริปต์ runit.shสคริปต์ดูเหมือนว่า:

#!/bin/bash
module load python/2.7.2
arg1=myarg1
arg2=15
arg3=$5
/path/to/python_exe.py -a $arg1 -b $arg2 -c $arg3

Howver เมื่อฉันเพิ่งเรียกใช้./runit.shมันขาย "โมดูล: คำสั่งไม่พบ" source runit.shอย่างไรก็ตามเมื่อฉันโหลดโมดูลอย่างถูกต้อง ทำไมนี้

คำตอบ:


13

เนื่องจากmoduleคำสั่งเป็นฟังก์ชันนามแฝงหรือเชลล์ (ดู "การกำหนดค่าเริ่มต้นแพ็คเกจ " ใน โมดูล (1) ) เมื่อคุณพูดsource runit.shมันเหมือนกับการพิมพ์moduleคำสั่งลงในเชลล์เชิงโต้ตอบของคุณโดยตรง แต่เมื่อคุณพูด./runit.shคุณกำลังเรียกใช้เชลล์ใหม่ที่ไม่มีการโต้ตอบ โดยทั่วไปแล้วเชลล์ที่ไม่มีการโต้ตอบจะไม่มีการตั้งค่าสมนามมาตรฐานและการทำงานของเชลล์

module (1)กล่าวว่า“ แพ็กเกจ Modules และคำสั่งโมดูลจะถูกเตรียมใช้งานเมื่อสคริปต์การเริ่มต้นเฉพาะเชลล์มีที่มาจากเชลล์ สคริปต์สร้างคำสั่งโมดูลไม่ว่าจะเป็นฟังก์ชันนามแฝงหรือเชลล์, …” หากคุณต้องการเรียกใช้moduleคำสั่งในสคริปต์ให้ค้นหาสคริปต์การเริ่มต้นที่กำหนดmoduleคำสั่งsourceจากสคริปต์


นี่คือความแตกต่างระหว่างการใช้. bashrc และ. bash_profile หรือไม่ มีเพียงหนึ่งในนั้นเท่านั้นที่มีรูทีนการเริ่มต้นเพื่อเริ่มต้นระบบโมดูลสำหรับการใช้งาน
drjrm3

ฉันไม่แน่ใจว่าสิ่งที่คุณถาม แต่: bash ทำสิ่งต่อไปนี้ตามค่าเริ่มต้น (การกระทำเหล่านี้สามารถแทนที่ได้โดยตัวเลือก): ล็อกอินเชลล์อ่าน `~ / .bash_profile 'แต่ไม่ใช่~/.bashrcเชลล์เชิงโต้ตอบที่ไม่ใช่เชลล์ล็อกอิน (เช่นสิ่งที่คุณได้รับหากคุณพิมพ์bashเป็น คำสั่ง) อ่าน~/.bashrcแต่ไม่ใช่~/.bash_profileและเชลล์ที่ไม่มีการโต้ตอบ (เช่นหนึ่งที่รันสคริปต์) ไม่อ่าน … (ต่อ)
สกอตต์

(ต่อ) ... นี่อาจเป็นเหตุผลที่ไซรัสแนะนำ#!/bin/bash -i- เนื่องจากตัวเลือกที่ทำให้เปลือกโต้ตอบและดังนั้นจึงจะทำให้การอ่าน-i ~/.bashrcIMHO มันเกินความจริงเพราะโหมดอินเตอร์แอคทีฟอาจมาพร้อมกับกระเป๋าที่ไม่ต้องการ (เช่นเขียนถึง~/.bash_history) ในทางกลับกันถ้าmoduleนิยามเป็น alias (ตรงข้ามกับฟังก์ชัน shell) มันจะไม่ทำงานใน shell ที่ไม่มีการโต้ตอบเว้นแต่คุณจะพูดshopt -s expand_aliasesดังนั้นบางทีคำตอบของ Cyrus อาจเป็นคำตอบที่ดีที่สุด
สกอตต์

4

ดูเหมือนว่าการเรียกง่าย ๆ ของเชลล์ในระบบของคุณจะไม่ได้รับสืบทอดนามแฝง (หรือฟังก์ชั่น) ที่มีการกำหนดไว้moduleดังนั้นเชลล์ไม่สามารถค้นหาได้ (ดูด้านล่างของบันทึกด้วยข้อความที่ตัดตอนมา) ลองtype moduleจากพรอมต์เพื่อดูว่าmoduleมีการกำหนดไว้อย่างไร

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

เกี่ยวกับความแตกต่างระหว่างการจัดทำสคริปต์และดำเนินการคุณสามารถอ่านได้ใน SuperUser Sep 2009หรือDec 2009 , Ubuntu Feb 2011 , Unix Aug 2011 , Stackoverflow Dec 2012หรือในที่อื่น ๆ

ในเรื่องนี้ในส่วนโมดูลไฟล์ มีคำเตือน :

... ตัวแปรสภาพแวดล้อมไม่ได้รับการตั้งค่าเมื่อยกเลิกการโหลด modulefile ดังนั้นจึงเป็นไปได้ที่จะโหลด modulefile แล้วยกเลิกการโหลดโดยไม่ให้ตัวแปรสภาพแวดล้อมกลับสู่สถานะก่อนหน้า

ดังนั้นดูเหมือนว่าฉลาดมากขึ้นในการดำเนินการในสคริปต์

เพื่อให้สำเร็จหลังฉันสามารถคิด:

  1. หากต้องการใช้เชลล์แบบโต้ตอบให้เพิกเฉยประวัติเฉพาะของเชลล์ปัจจุบันโดยปรับเปลี่ยนShebangของสคริปต์ด้วย

    #!/bin/bash -i

    เชลล์แบบโต้ตอบอ่านคำสั่งจากอินพุตของผู้ใช้บน tty เหนือสิ่งอื่นใดเช่นเชลล์อ่านไฟล์เริ่มต้นเมื่อเปิดใช้งานแสดงพรอมต์และเปิดใช้งานการควบคุมงานโดยค่าเริ่มต้น ...

  2. หากคุณต้องการสืบทอดเรื่องราวเฉพาะของเชลล์ปัจจุบันแทนคุณสามารถลองแหล่งที่มามัน ... แต่ในเชลล์ย่อย

    ( source runit.sh )
  3. ลองค้นหานามแฝง / ฟังก์ชั่นปัจจุบันmoduleด้วยtype moduleแล้วแก้ไขตามด้วยสคริปต์ของคุณ หมายเหตุตัวแปรสภาพแวดล้อมบางตัวไม่สามารถตั้งค่าmoduleได้ ถ้าคุณต้องการคุณสามารถค้นหาเริ่มต้นสคริปต์ในไดเรกทอรี
    $MODULESHOME/init/<shell>


ความคิดเห็น
ตามที่จำได้ในคำถาม & คำตอบของโมดูล

กระบวนการลูก (สคริปต์) ไม่สามารถเปลี่ยนสภาพแวดล้อมกระบวนการหลัก การโหลดโมดูลในสคริปต์มีผลกับสภาพแวดล้อมของสคริปต์เท่านั้น วิธีเดียวที่คุณสามารถเปลี่ยนสคริปต์สภาพแวดล้อมปัจจุบันคือแหล่งสคริปต์ซึ่งอ่านมันในกระบวนการปัจจุบัน

ดังนั้นหากคุณต้องการหลีกเลี่ยงการปรับเปลี่ยนสภาพแวดล้อมปัจจุบันฉันคิดว่ามันเป็นการดีกว่าที่จะพยายามเปลี่ยนshebang (1) หรือแหล่งสคริปต์ใน subshell (2) ฉันไม่แน่ใจเกี่ยวกับการใช้งานของกรณี (3)


หมายเหตุ
ข้อความที่ตัดตอนมาจากหน้าคู่มือและหน้ารายละเอียดของโมดูล

moduleเป็นส่วนต่อประสานผู้ใช้กับแพ็คเกจ Modules moduleนามแฝงหรือฟังก์ชั่นรันmodulecmdโปรแกรมและมีเปลือกประเมินออกคำสั่งของ อาร์กิวเมนต์แรกที่modulecmdระบุชนิดของเชลล์

แพ็กเกจ Modules และmoduleคำสั่งถูกเตรียมข้อมูลเบื้องต้นเมื่อสคริปต์การกำหนดค่าเริ่มต้นเฉพาะเชลล์มีที่มาในเชลล์ สคริปต์สร้างคำสั่งโมดูลไม่ว่าจะเป็น alias หรือฟังก์ชัน shell สร้างตัวแปรสภาวะแวดล้อม Modules


แต่เขาไม่ได้พยายามที่จะส่งผลกระทบต่อสภาพแวดล้อมของกระบวนการหลัก; เขาแค่พยายามทำให้ Python ของเขาสามารถเรียกใช้จากสคริปต์ได้ นอกจากนี้คำตอบของคุณไม่ได้อธิบายว่าทำไมเขาถึงได้รับข้อความแสดงข้อผิดพลาด“ โมดูล: ไม่พบคำสั่ง”
สกอตต์

@Scott ขอบคุณ ก่อนที่ฉันจะตัดส่วนที่ใหญ่กว่าของคำตอบโดยไม่ได้ตั้งใจและโพสต์เพียงบางส่วน คำตอบเขียนใหม่
Hastur

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