Khi tôi sử dụng bất kỳ lệnh nào với sudo, các biến môi trường không có ở đó. Ví dụ: sau khi đặt HTTP_PROXY, lệnh wgethoạt động tốt mà không có sudo. Tuy nhiên nếu tôi gõ sudo wgetthì nó báo không thể bỏ qua cài đặt proxy.
Khi tôi sử dụng bất kỳ lệnh nào với sudo, các biến môi trường không có ở đó. Ví dụ: sau khi đặt HTTP_PROXY, lệnh wgethoạt động tốt mà không có sudo. Tuy nhiên nếu tôi gõ sudo wgetthì nó báo không thể bỏ qua cài đặt proxy.
Câu trả lời:
Đầu tiên bạn cần phải export HTTP_PROXY. Thứ hai, bạn cần đọc man sudokỹ, và chú ý đến -Ecờ. Những công việc này:
$ export HTTP_PROXY=foof
$ sudo -E bash -c 'echo $HTTP_PROXY'
Đây là trích dẫn từ trang người đàn ông:
-E, --preserve-env
Indicates to the security policy that the user wishes to preserve their
existing environment variables. The security policy may return an error
if the user does not have permission to preserve the environment.
LC_*biến. Vì vậy, chỉ cần làm export LOL_FOO=$LC_FOOvà sử dụng LOL_FOOthay thế.
PATHvào .bashrctệp - giả sử , export PATH=myPath:$PATH. Nếu tôi gõ sudo -E bash -c 'echo $PATH', thì PATHkhông chứa myPath có lẽ vì sudođã vô hiệu hóa giá trị cục bộ PATHtrước khi gọi bash. Thay vào đó, tôi đã tìm thấy câu trả lời bên dưới stackoverflow.com/a/33183620/5459638 có hiệu lực, đó làsudo PATH=$PATH command
Mẹo nhỏ là thêm các biến môi trường vào sudoerstệp thông qua sudo visudolệnh và thêm các dòng sau:
Defaults env_keep += "ftp_proxy http_proxy https_proxy no_proxy"
lấy từ wiki ArchLinux .
Đối với Ubuntu 14, bạn cần chỉ định trong các dòng riêng biệt vì nó trả về lỗi cho các dòng đa biến:
Defaults env_keep += "http_proxy"
Defaults env_keep += "https_proxy"
Defaults env_keep += "HTTP_PROXY"
Defaults env_keep += "HTTPS_PROXY"
sudo -Elà cách chắc chắn để adhoc có được hiệu quả tương tự cho một lần, mặc dù vậy
etc/sudoerstrực tiếp. Thay vào đó, hãy sử dụng visudolệnh kiểm tra cú pháp của bạn trước khi ghi đè sudoerstệp. Bằng cách đó, bạn không tự khóa nếu bạn mắc lỗi trong khi chỉnh sửa.
Đối với các biến riêng lẻ bạn muốn cung cấp trên cơ sở một lần, bạn có thể biến nó thành một phần của lệnh.
sudo http_proxy=$http_proxy wget "http://stackoverflow.com"
packagesố myPath được thêm vào PATHtrong .bashrctệp (với exportmệnh đề). Sau đó sudo PATH=$PATH which packagetìm câu trả lời đúng, không giống như sudo which package. Tuy nhiên, sudo PATH=$PATH packagekhông đi xa hơn sudo package(không tìm thấy tệp). Mặt khác, khởi động một đồng bằng packagetừ một chiếc vỏ được gọi với sudo bashbảo tồn con đường mở rộng và trao packagequyền sudo (hai con chim bồ câu với một viên đá). Vì vậy, phản hồi thực sự phụ thuộc vào lệnh bạn đang khởi chạy
Tôi đã đưa ra một giải pháp độc đáo bởi vì:
sudo -E "$@" đã rò rỉ các biến gây ra vấn đề cho lệnh của tôisudo VAR1="$VAR1" ... VAR42="$VAR42" "$@" dài và xấu trong trường hợp của tôi#!/bin/bash
function sudo_exports(){
eval sudo $(for x in $_EXPORTS; do printf '%q=%q ' "$x" "${!x}"; done;) "$@"
}
# create a test script to call as sudo
echo 'echo Forty-Two is $VAR42' > sudo_test.sh
chmod +x sudo_test.sh
export VAR42="The Answer to the Ultimate Question of Life, The Universe, and Everything."
export _EXPORTS="_EXPORTS VAR1 VAR2 VAR3 VAR4 VAR5 VAR6 VAR7 VAR8 VAR9 VAR10 VAR11 VAR12 VAR13 VAR14 VAR15 VAR16 VAR17 VAR18 VAR19 VAR20 VAR21 VAR22 VAR23 VAR24 VAR25 VAR26 VAR27 VAR28 VAR29 VAR30 VAR31 VAR32 VAR33 VAR34 VAR35 VAR36 VAR37 VAR38 VAR39 VAR40 VAR41 VAR42"
# clean function style
sudo_exports ./sudo_test.sh
# or just use the content of the function
eval sudo $(for x in $_EXPORTS; do printf '%q=%q ' "$x" "${!x}"; done;) ./sudo_test.sh
$ ./demo.sh
Forty-Two is The Answer to the Ultimate Question of Life, The Universe, and Everything.
Forty-Two is The Answer to the Ultimate Question of Life, The Universe, and Everything.
Điều này được thực hiện bởi một tính năng của nội dung bash printf. Việc %qtạo ra một chuỗi trích dẫn shell. Không giống như mở rộng tham số trong bash 4.4 , điều này hoạt động trong các phiên bản bash <4.0
Nếu bạn có nhu cầu giữ các biến môi trường trong một tập lệnh, bạn có thể đặt lệnh của bạn trong một tài liệu ở đây như thế này. Đặc biệt là nếu bạn có nhiều biến để thiết lập mọi thứ trông gọn gàng theo cách này.
# prepare a script e.g. for running maven
runmaven=/tmp/runmaven$$
# create the script with a here document
cat << EOF > $runmaven
#!/bin/bash
# run the maven clean with environment variables set
export ANT_HOME=/usr/share/ant
export MAKEFLAGS=-j4
mvn clean install
EOF
# make the script executable
chmod +x $runmaven
# run it
sudo $runmaven
# remove it or comment out to keep
rm $runmaven