Làm thế nào để làm cho dịch vụ unix thấy các biến môi trường?


52

Tôi đã đặt biến môi trường của mình bằng cách sử dụng /etc/profile:

export VAR=/home/userhome

Sau đó, nếu tôi làm điều echo $VARđó cho thấy/home/userhome

Nhưng khi tôi đặt tham chiếu đến biến này vào /etc/init.d/servicenametệp, nó không thể tìm thấy biến này. Khi tôi chạy service servicename statusbằng /etc/init.d/servicenametệp có nội dung sau:

case "$1" in
status)    
    cd $VAR/dir
    ;;
esac

nó nói rằng /dir: No such file or directory

Nhưng nó hoạt động nếu tôi chạy /etc/init.d/servicename statusthay vìservice servicename status

Làm thế nào tôi có thể làm cho dịch vụ unix thấy các biến môi trường?


Lưu ý rằng việc gọi rctrực tiếp tập lệnh Hệ thống 5 cũng không hoạt động theo cách đó trên các hệ điều hành hệ thống, vì tất cả các lệnh của tập lệnh được chuyển thành các yêu cầu của systemctlmột móc ẩn.
JdeBP

Câu trả lời:


70

Vấn đề là servicedải tất cả các biến môi trường TERM, PATHLANG, đó là một điều tốt. Nếu bạn đang thực thi tập lệnh trực tiếp, không có gì loại bỏ các biến môi trường để mọi thứ hoạt động.

Bạn không muốn dựa vào các biến môi trường bên ngoài vì khi khởi động, biến môi trường có thể không xuất hiện và hệ thống init của bạn có thể sẽ không đặt nó.

Nếu bạn vẫn muốn dựa vào các biến như vậy, hãy tìm một tệp và đọc các biến từ đó, ví dụ: tạo /etc/default/servicenamevới nội dung:

VAR=value

và lấy nó từ tập lệnh init của bạn, vd:

[ -f /etc/default/service-name ] && . /etc/default/service-name

if [ -z "$VAR" ] ;  then
  echo "VAR is not set, please set it in /etc/default/service-name" >&2
  exit 1
fi

case "$1" in
status)    
    cd "$VAR"/dir
    ;;
esac

13
Rất hữu ích, cảm ơn. Đối với những người mới sử dụng Linux khác, đây là công cụ Bash khó hiểu. [ ... ]là một tốc ký cho một bài kiểm tra có điều kiện; thấy câu trả lời này . -flà một ifđối số để kiểm tra nếu tập tin tồn tại. &&là một toán tử ngắn mạch: chỉ thực hiện lệnh thứ hai nếu thoát thứ nhất với 0. .toán tử nguồn hoặc dấu chấm: đọc và thực thi các lệnh từ đối số tên tệp. -zlà một ifđối số để kiểm tra chuỗi có độ dài bằng không. >&2gửi đầu ra đến stderr. Xem thêm Giới thiệu về nếu .
Mark Berry

@Mark BlackBerry -flà một phần của [, không phải if.
Chris Down

@ChrisDown, cảm ơn. Vì vậy, " [ ... ]là một tốc ký cho một testlệnh có điều kiện ; hãy xem câu trả lời này . -fLà một testđối số để kiểm tra xem một tệp có tồn tại không."
Mark Berry

@Mark BlackBerry Đúng. Bạn có thể nghĩ [(hoặc test) chỉ là một lệnh khác - tất cả đều ifthực hiện một số hành động dựa trên trạng thái thoát.
Chris Down

Tôi đã chạy vào một tình huống tương tự như này, nhưng tôi không cần phải $VARđược trong init script, tôi cần nó để được cung cấp cho một chương trình khác nhau 2 hoặc 3 cuộc gọi hạ lưu của init script. Ví dụ. init script gọi start-stop-daemon gọi Chương trình 1 (Java) gọi Chương trình 2 cần $VAR. Tôi đã thử mẹo trong câu trả lời này nhưng nó dường như không hoạt động trong tình huống của tôi. Làm thế nào tôi có thể đảm bảo rằng $VARsẽ có sẵn cho Chương trình 2?
Thất

1

Trong trường hợp của tôi, tôi cần một RAILS_ENVcái được đặt trong /etc/bash.bashrc: export RAILS_ENV=staging. Tôi đã thêm $(grep RAILS_ENV /etc/bash.bashrc)và điều đó làm cho biến có sẵn cho kịch bản. Tôi đã làm theo cách này vì vậy tôi không phải bao gồm phần còn lại của tệp.


-1

Một giải pháp xấu xí cũng sẽ hoạt động:

function exec() {
    args=( $@ )
    command=${args[0]}
    dummy=${args[1]}
    whoami=`whoami`
    if [ -z "$dummy" ]; then
        me=`basename $0`
        runuser -l ${whoami} -c "bash /etc/init.d/${me} ${command} dummy"
    else
       printenv
   fi
}

case $1 in
    status)
        status
        ;;
    start|stop|kill|restart)
        exec $*
        ;;
    *)
        usage
esac
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.