Làm thế nào để hiển thị giá trị hiện tại của biến môi trường?


23

Khi tôi kiểm tra môi trường hệ thống của mình, rất nhiều biến môi trường sẽ xuất hiện. Làm thế nào tôi có thể chỉ tìm kiếm một biến cụ thể?

Một cuốn sách tôi đang đọc nói:

Đôi khi số lượng biến trong môi trường của bạn tăng khá lớn, đến mức bạn không muốn thấy tất cả các giá trị được hiển thị khi bạn quan tâm chỉ một. Nếu đây là trường hợp, bạn có thể sử dụng echolệnh để hiển thị giá trị hiện tại của biến môi trường.

Làm thế nào để tôi làm điều này trong một thiết bị đầu cuối Linux?

Câu trả lời:


24

Chỉ:

echo "$VARIABLENAME"

Ví dụ cho biến môi trường $HOME, sử dụng:

echo "$HOME"

Sau đó in một cái gì đó tương tự như:

/home/username

Chỉnh sửa : theo nhận xét của Stéphane Chazelas , có thể tốt hơn nếu bạn sử dụng printenvthay vì echo:

printenv HOME

4
Bạn đã quên dấu ngoặc kép (trừ khi bạn ngụ ý cú pháp zsh hoặc RC / es). echolà một lựa chọn kém của một lệnh vì nó có thể biến đổi nội dung của biến. Nó sẽ xuất nội dung của tham số shell cùng tên. Đó là không nhất thiết phải giống nhau nếu sử dụng vỏ Bourne hay cho env VAR như 1, *ví dụ. Và bạn không thể sử dụng phương pháp đó cho các env vars có tên không hợp lệ làm tên biến shell.
Stéphane Chazelas

5
Cũng lưu ý rằng nếu có một số mục môi trường có cùng tên (OK, trường hợp bệnh lý), mục nào bạn sẽ nhận được tùy thuộc vào trình bao (thường là mục đầu tiên hoặc mục cuối). printenv VARsẽ hiển thị tất cả (ít nhất là cho việc triển khai GNU).
Stéphane Chazelas

9

Bằng cách thực hiện:

printenv

Bạn sẽ thấy tất cả các biến môi trường. Để biết thêm thông tin bạn có thể xem tại:

https://www.digitalocean.com/community/tutorials/how-to-read-and-set-enviral-and-shell-variables-on-a-linux-vps


2
Để đến gần để thực sự trả lời câu hỏi, printenv variablenamesẽ chỉ hiển thị biến được đặt tên; ví dụ, printenv  HOMEsẽ làm gần giống như echo  "$HOME".
G-Man nói 'Phục hồi Monica'

5

Điều quan trọng là phải hiểu rằng mỗi quá trình có tập hợp các biến môi trường riêng.

Khi một quy trình gọi cuộc gọi fork()hệ thống, một quy trình thứ hai ( con ) giống hệt với quy trình đầu tiên ( cha mẹ ) được tạo ra ( bản sao này bao gồm môi trường, nằm ngay bên trên ngăn xếp (hoặc ngay bên dưới, tùy thuộc vào cách bạn nghĩ về ngăn xếp :-)- nhưng trong unix / linux stack mọc xuống từ địa chỉ cao).

Thông thường, tiến trình con sau đó sẽ gọi cuộc gọi execve()hệ thống, nó sẽ loại bỏ mọi thứ trong bộ nhớ (ảo) của nó và tái cấu trúc nó từ phần mã và dữ liệu trong tệp nhị phân đã chỉ định.

Tuy nhiên, khi nó xây dựng lại ngăn xếp, nó sao chép môi trường và các chuỗi đối số được truyền execve()vào ngăn xếp trước (theo thứ tự đó), trước khi gọi main()hàm (rất nhiều công việc được thực hiện trong crt0mã bootstrap sau khi execve()trả về (vào mục nhập điểm quy định trong nhị phân)).

Có các hàm bao cho execve()cuộc gọi hệ thống trong thư viện C sẽ vượt qua môi trường hiện tại (tức là bản sao của môi trường cha mẹ), thay vì người gọi cung cấp nó (vì vậy, thực tế là đứa trẻ sẽ thừa hưởng môi trường của cha mẹ) - xem environ(7).

Hãy thử chạy (với quyền root) lệnh ps axeww | less... điều này sẽ cho bạn thấy môi trường cho tất cả các quy trình! Một điều thú vị là process id 1 (tức là initquá trình - quá trình đầu tiên được tạo bởi kernel khi khởi động).

Nếu bạn muốn xem xét môi trường cho một quy trình cụ thể (và bạn biết đó là quy trình id), hãy thử chạy lệnh cat /proc/<PID>/environ(thay thế <PID>bằng id quy trình).

Lưu ý rằng nếu một quy trình có đủ đặc quyền, nó có thể viết lại ngăn xếp của chính nó, điều này có thể gây khó khăn cho việc biết môi trường của nó là gì - bạn sẽ thấy một số quy trình daemon như thế này trong đầu ra ps.

Nhưng cuối cùng, tất cả những chiếc bánh quế này đều hiểu rõ những gì @chaos đã nói ở trên, nếu bạn muốn xem giá trị hiện tại của một biến môi trường cụ thể trong quy trình shell của bạn, chỉ cần sử dụng lệnh (dựng sẵn) echo "$<NAME>"(thay thế <NAME>bằng tên của biến môi trường mà bạn quan tâm) ... chỉ cần lưu ý rằng cùng một biến có thể có một giá trị khác hoặc hoàn toàn không tồn tại trong một quy trình khác.


1
(1) Lưu ý rằng etùy chọn ps/proc/…/environtệp đặc biệt có thể không tồn tại trên tất cả các hệ thống. (2) AFAIK, mọi quy trình Unix đều có đặc quyền viết lại ngăn xếp của nó và sửa đổi các biến môi trường của nó. (3) Để thảo luận thêm, hãy xem Biến môi trường thuộc về ai? (trên Siêu người dùng ).
G-Man nói 'Phục hồi Monica'

Trong đầu tôi đã có một số hệ thống có cách để ngăn chặn một quá trình không có đặc quyền "che giấu" các đối số và môi trường dòng lệnh của nó, ví dụ như từ root đang chạy ps... nhưng bây giờ bạn đã nhấn mạnh điểm này, tôi không thể nhớ tại sao tôi nghĩ rằng.
Murray Jensen

@M bồJensen theo một số cuộc thảo luận về câu hỏi được bình chọn cao mà tôi đã hỏi về việc Curliến ẩn giấu các đối số của mình trong ps, điều đó không được xác định trong POSIX cho dù ps trả về các đối số như ban đầu được chuyển đến quy trình, hoặc một bản sao mà quá trình có thể đã sửa đổi sau đó bắt đầu Một số hệ thống (tôi nghĩ Solaris ??) hiển thị các đối số ban đầu không có vấn đề gì. (Đây là liên kết.) Đây có thể là những gì bạn đã nghĩ đến. :)
tự đại diện

Chơi lô tô! Vâng, tất nhiên Solaris thực hiện điều này một cách "chính xác" :-) Cảm ơn bạn đã bồi dưỡng ...
Murray Jensen

1

Bạn có thể nhận được những gì bạn đang tìm kiếm với export:

export | grep HOME

Sẽ hiển thị nội dung của $HOMEbiến.


1

nếu bạn phải đặt nhiều vars:

  ( set -o posix ; set ) | sort >~/vars.before

sau khi đã đặt chúng:

  ( set -o posix ; set ) | sort >~/vars.after

hơn hiển thị những gì đã được đặt:

  comm -3 ~/vars.before ~/vars.after | perl -ne 's#\s+##g;print "\n $_ "'

Bằng cách này, bạn sẽ sớm tìm thấy chính mình, làm việc với nhiều bộ vars shell được xác định trước trong các tệp cnf, kết hợp với tmux sẽ giúp bạn trở thành bậc thầy về quản lý cấu hình trong môi trường shell:

  # ---------------------------------------------------------
  # cat cnf/qto.dev.host-name.cnf
  # [MainSection]
  # postgres_db_name     = dev_qto
  # postgres_db_host     = host-name
  #
  # call by: doParseCnfEnvVars cnf/qto.dev.host-name.cnf
  # ---------------------------------------------------------
  doParseCnfEnvVars(){

     cnf_file=$1;shift 1;
     test -z "$cnf_file" && echo " you should set the cnf_file !!!"

     INI_SECTION=MainSection

     ( set -o posix ; set ) | sort >~/vars.before

     eval `sed -e 's/[[:space:]]*\=[[:space:]]*/=/g' \
        -e 's/#.*$//' \
        -e 's/[[:space:]]*$//' \
        -e 's/^[[:space:]]*//' \
        -e "s/^\(.*\)=\([^\"']*\)$/export \1=\"\2\"/" \
        < $cnf_file \
        | sed -n -e "/^\[$INI_SECTION\]/,/^\s*\[/{/^[^#].*\=.*/p;}"`

     # and post-register for nice logging
     ( set -o posix ; set ) | sort >~/vars.after

     echo "INFO added the following vars from section: [$INI_SECTION]"
     comm -3 ~/vars.before ~/vars.after | perl -ne 's#\s+##g;print "\n $_ "'
  }
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.