Cách xác định hàm Bash có thể được sử dụng bởi các tập lệnh khác nhau


13

Tôi đã xác định một bashchức năng trong ~/.bashrctập tin của tôi . Điều này cho phép tôi sử dụng nó trong thiết bị đầu cuối vỏ. Tuy nhiên, nó dường như không tồn tại khi tôi gọi nó từ trong một kịch bản.

Làm thế nào tôi có thể xác định một bashchức năng được sử dụng bởi các kịch bản?


Nhưng về cơ bản .bash_profile của tôi đọc tệp .basrc, vì vậy tôi mong đợi kết quả sẽ giống nhau bất kể tôi sử dụng shell đăng nhập hay không đăng nhập.
Onurenio

Bạn đang sử dụng /bin/shtrong dòng shebang?
Kevin

Câu trả lời:


9

~/.bash_profile~/.bashrckhông được đọc bởi các tập lệnh và các chức năng không được xuất theo mặc định. Để làm như vậy, bạn có thể sử dụng export -fnhư vậy:

$ cat > script << 'EOF'
#!/bin/bash
foo
EOF
$ chmod a+x script
$ ./script
./script: line 2: foo: command not found
$ foo() { echo "works" ; } 
$ export -f foo
$ ./script
works

export -f foocũng có thể được gọi ~/.bash_profileđể làm cho chức năng này có sẵn cho các tập lệnh sau khi đăng nhập. Được cảnh báo rằng export -fkhông phải là di động.

Một giải pháp tốt hơn sẽ là nguồn tệp chứa hàm sử dụng . file. Điều này dễ mang theo hơn nhiều và không phụ thuộc vào môi trường của bạn được thiết lập theo một cách cụ thể.


Tại sao không chỉ khai báo một chức năng như function myFunction { ... }trong ~/.bash_profilevà bạn tốt để đi?
lưỡng cư

Nếu tôi hiểu đúng câu trả lời của bạn (liên quan đến việc tìm nguồn tệp với hàm), điều này có nghĩa là tôi phải lấy nguồn tệp rõ ràng trong mỗi tập lệnh, điều này khá khó chịu. Điều này không phức tạp hơn nhiều so với việc chỉ sao chép chính chức năng trong mỗi tập lệnh. Tôi sẽ lưu một số dòng, chắc chắn, nhưng đó là tất cả. Tuy nhiên, exportgiải pháp có vẻ hoạt động đúng. Cảm ơn.
Onurenio

@foampile, đây chính xác là những gì tôi đã làm và không hoạt động khi gọi hàm từ tập lệnh.
Onurenio

1
@Onturenio: phương pháp thứ hai @ chris-down đề xuất thực sự tốt hơn: 1) Khi ai đó đọc tập lệnh, họ nhận thấy rằng nó cần một số foochức năng từ một số file2) Bạn có thể kiểm soát nội dung của nó filetốt hơn là đảm bảo rằng trình vỏ gọi đã không thay đổi footrước khi gọi kịch bản của bạn. fileVí dụ, bạn có thể thêm kiểm tra an toàn để đảm bảo rằng nó không bị làm phiền. (không dễ, nhưng có thể). (tốt, bạn cũng có thể thực hiện các kiểm tra đó đối với chức năng foo đã xác định ... nhưng bạn có được sự trôi dạt của mình ^^ Tôi nghĩ rằng phương pháp 2 sạch hơn.) 3) filesẽ chỉ chứa những gì cần thiết, không nhiều hơn.
Olivier Dulac

8

.bashrcchỉ được đọc bởi các vỏ tương tác. (Trên thực tế, đó là một sự đơn giản hóa: bash là kỳ quặc trong lĩnh vực này Bash không đọc. .bashrcNếu đó là một vỏ đăng nhập, tương tác hay không Và có một ngoại lệ thậm chí đến ngoại lệ:. Nếu quá trình cha mẹ bash là rshdhay sshd, sau đó bash không đọc .bashrc, cho dù đó là tương tác hay không.)

Đặt định nghĩa hàm của bạn vào một tệp ở một nơi đã biết và sử dụng nội dung .(cũng được đánh vần source) để đưa tệp đó vào tập lệnh.

$ cat ~/lib/bash/my_functions.bash
foo () {

$ cat ~/bin/myscript
#!/bin/bash
. ~/lib/bash/my_functions.bash
foo bar

Nếu bạn muốn, bạn có thể làm theo tính năng tự động tải của ksh. Đặt từng định nghĩa hàm trong một tệp có cùng tên với hàm. Liệt kê các thư mục chứa các định nghĩa hàm trong FPATHbiến (danh sách các thư mục được phân tách bằng dấu hai chấm). Đây là một xấp xỉ thô của ksh's autoloadthực sự tải chức năng ngay lập tức thay vì theo yêu cầu:

autoload () {
  set -- "$(set +f; IFS=:;
            for d in $FPATH; do
              if [ -r "$d/$1" ]; then echo -E "$d/$1"; break; fi;
            done)"
  [[ -n $1 ]] && . "$1"
}

+1 cho tự động tải, mặc dù tôi khuyên bạn nên sử dụng những cái đi kèm với bash. Cái mới nhất hỗ trợ tải lười biếng.
Sao biển

0

Bạn có cần một chức năng? Nếu không, hãy cân nhắc rút logic ra thành một tập lệnh Bash riêng, độc lập trong bạn $PATH. Ví dụ, tôi đã có cái này trong ~/.bashrc:

# echo public IP address
alias wanip='dig +short myip.opendns.com @resolver1.opendns.com'

~/binlà của tôi $PATH, vì vậy tôi đã tạo ra ~/bin/wanipvới các nội dung sau:

#!/bin/bash

# echo public IP address
dig +short myip.opendns.com @resolver1.opendns.com

Và chạy chmod 0755 ~/bin/wanipđể làm cho nó thực thi. Bây giờ tôi có thể thực thi waniptừ các kịch bản khác.

Tôi thích có wanipmột kịch bản Bash độc lập. Nó nhắc nhở tôi rằng tôi muốn logic này thường có sẵn (ngoài chỉ trong phiên Bash tương tác hiện tại của tôi). Kịch bản đóng gói độc đáo logic và tài liệu cho cùng.

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.