Tại sao tôi không thể tải các mô-đun trong khi thực hiện tập lệnh bash của mình, nhưng chỉ khi tìm nguồn cung ứng?


12

Tôi đang sử dụng các mô-đun để kiểm soát các gói trên hệ thống của mình và tôi đã python/2.7.2cài đặt dưới dạng một mô-đun. Tôi có một thực thi python đơn giản python_exe.pymà tôi sẽ gọi từ một kịch bản 'lái xe' đơn giản runit.sh. runit.shkịch bản trông giống như:

#!/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

Tuy nhiên, khi tôi vừa chạy ./runit.sh, nó bán cho tôi "mô-đun: lệnh không tìm thấy". Khi tôi source runit.sh, tuy nhiên, nó tải chính xác mô-đun. Tại sao lại thế này?

Câu trả lời:


13

Bởi vì modulelệnh là một bí danh hoặc hàm shell (xem " Khởi tạo gói " trong mô-đun (1) ). Khi bạn nói source runit.sh, nó giống như gõ modulelệnh trực tiếp vào vỏ tương tác của bạn. Nhưng khi bạn nói ./runit.sh, bạn đang chạy một vỏ mới, không tương tác. Các shell không tương tác thường không có các bí danh chuẩn và các hàm shell được thiết lập.

mô-đun (1) cho biết, gói Gói mô-đun và lệnh mô-đun được khởi tạo khi tập lệnh khởi tạo dành riêng cho hệ vỏ được lấy nguồn vào trình bao. Kịch bản lệnh tạo mô-đun , dưới dạng bí danh hoặc hàm shell, Giá đỡ Nếu bạn cần chạy modulelệnh trong tập lệnh, hãy tìm tập lệnh khởi tạo xác định modulelệnh và sourcetừ tập lệnh.


Đây có phải là sự khác biệt giữa việc sử dụng .bashrc và .bash_profile? Chỉ một trong số họ có các thói quen khởi tạo để khởi động hệ thống mô-đun để sử dụng.
drjrm3

Tôi không chắc chắn chính xác những gì bạn đang hỏi. Nhưng: bash thực hiện các thao tác sau theo mặc định (các hành động này có thể bị ghi đè bởi các tùy chọn): vỏ đăng nhập ghi `~ / .bash_profile` nhưng không ~/.bashrc, vỏ tương tác không phải là vỏ đăng nhập (ví dụ: những gì bạn nhận được nếu bạn nhập bashnhư một lệnh) đọc ~/.bashrcnhưng không ~/.bash_profile, và trình bao không tương tác (ví dụ: một trình chạy tập lệnh) không đọc. Tiết (Cont'd)
Scott

(Tiếp theo) Đây có lẽ là lý do Cyrus đề xuất #!/bin/bash -i- vì -itùy chọn này tạo ra lớp vỏ tương tác và do đó sẽ khiến nó đọc được ~/.bashrc. IMHO, đó là quá mức cần thiết, bởi vì chế độ tương tác có thể đi kèm với hành lý không mong muốn (như viết thư ~/.bash_history). Mặt khác, nếu moduleđược định nghĩa là bí danh (trái ngược với hàm shell), nó sẽ không hoạt động trong một vỏ không tương tác trừ khi bạn nói shopt -s expand_aliases, vì vậy có lẽ câu trả lời của Cyrus là câu trả lời hay nhất.
Scott

4

Dường như việc gọi shell đơn giản trong hệ thống của bạn không kế thừa bí danh (hoặc hàm) được xác định module, do đó shell không thể tìm thấy nó (xem bên dưới ghi chú với đoạn trích). Hãy thử type moduletừ dấu nhắc để xem cách modulexác định hiện tại.

Về cơ bản với nguồn giống như nếu bạn viết từng dòng của kịch bản từ bàn phím.
Lưu ý rằng một mặt bạn đang kế thừa tất cả lịch sử cụ thể của trình bao hiện tại, nhưng ở một bên khác, trình bao hiện tại sẽ phải chịu mọi tác động của tập lệnh và modulelời gọi của bạn .

Về sự khác biệt giữa để tạo tập lệnh và để thực thi tập lệnh, bạn có thể đọc trên SuperUser tháng 9 năm 2009 hoặc tháng 12 năm 2009 , Ubuntu tháng 2 năm 2011 , Unix tháng 8 năm 2011 , Stackoverflow tháng 12 năm 2012 hoặc ở nhiều nơi khác.

Về vấn đề này trong Modulefiles phần có một cảnh báo :

... Các biến môi trường không được đặt khi dỡ tải một modulefile. Vì vậy, có thể tải một modulefile và sau đó dỡ bỏ nó mà không để các biến môi trường trở về trạng thái trước đó.

Vì vậy, có vẻ khôn ngoan hơn khi thực hiện nó trong một kịch bản .

Để hoàn thành cái sau tôi có thể nghĩ:

  1. Để sử dụng trình bao tương tác , bỏ qua lịch sử cụ thể của trình bao hiện tại, sửa đổi shebang của tập lệnh của bạn với

    #!/bin/bash -i

    Một vỏ tương tác đọc các lệnh từ đầu vào của người dùng trên một tty. Trong số những thứ khác, shell như vậy đọc các tệp khởi động khi kích hoạt, hiển thị lời nhắc và cho phép kiểm soát công việc theo mặc định ...

  2. Nếu thay vào đó bạn thích để kế thừa những câu chuyện cụ thể của vỏ hiện tại, bạn có thể thử để nguồn nó ... nhưng trong một subshell

    ( source runit.sh )
  3. Hãy cố gắng tìm ra bí danh hiện tại / chức năng modulevới type modulesau đó sửa đổi trong kết quả kịch bản của bạn. Lưu ý một số biến môi trường không thể được đặt cho module.
    Nếu bạn muốn bạn có thể tìm thấy các kịch bản khởi tạo trong thư mục $MODULESHOME/init/<shell>.


Nhận xét
Như đã nhớ trong hỏi đáp của các mô-đun

Một tiến trình con (script) không thể thay đổi môi trường tiến trình cha. Tải mô-đun trong tập lệnh chỉ ảnh hưởng đến môi trường của chính tập lệnh. Cách duy nhất để bạn có thể có một tập lệnh thay đổi môi trường hiện tại là lấy tập lệnh đọc tập lệnh đó vào quy trình hiện tại.

Vì vậy, nếu bạn muốn tránh sửa đổi môi trường hiện tại, tôi nghĩ tốt hơn hết là cố gắng thay đổi shebang (1) hoặc lấy tập lệnh trong một khung con (2). Tôi không hoàn toàn chắc chắn về khả năng sử dụng của vụ án (3).


Lưu ý
Trích từ trang hướng dẫn và mô tả của mô-đun

modulelà một giao diện người dùng cho gói Modules. Các modulebí danh hoặc chức năng thực thi cácmodulecmd chương trình và có vỏ đánh giá đầu ra của lệnh. Đối số đầu tiên để modulecmdchỉ định loại vỏ.

Gói Modules và modulelệnh được khởi tạo khi tập lệnh khởi tạo dành riêng cho shell được lấy nguồn từ shell . Kịch bản lệnh tạo mô-đun, dưới dạng bí danh hoặc hàm shell, tạo các biến môi trường Mô-đun


Nhưng anh ta không cố gắng làm ảnh hưởng đến môi trường của quá trình cha mẹ; anh ta chỉ cố gắng để Python thực thi của mình để chạy từ kịch bản . Bên cạnh đó, câu trả lời của bạn không giải thích lý do tại sao anh ta nhận được mô-đun dịch vụ: lệnh không tìm thấy thông báo lỗi.
Scott

@ Xin cảm ơn. Trước khi tôi vô tình cắt phần lớn hơn của câu trả lời và chỉ đăng một đoạn. Trả lời viết lại.
Hastur

1
+1.  ( source runit.sh )là một câu trả lời tốt; Tôi đã không nghĩ về nó. Và một bộ sưu tập tốt các tài liệu tham khảo.
Scott
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.