Xuất một biến env có sẵn ở tất cả các shell phụ, và có thể được sửa đổi không?


22

Giả sử tôi có

export MY_VAR=0

trong ~/.bashrc.

Tôi có một thiết bị đầu cuối gnome đã mở và trong thiết bị đầu cuối này, tôi thay đổi $MY_VARgiá trị thành 200. Vì vậy, nếu tôi làm

echo $MY_VAR

trong thiết bị đầu cuối này, 200được hiển thị.

Bây giờ, tôi đã mở một tab khác trong thiết bị đầu cuối gnome của mình và làm

echo $MY_VAR

... và thay vì 200, tôi có 0.

Tôi nên làm gì để duy trì giá trị 200 khi thiết bị đầu cuối sửa đổi biến môi trường, thực hiện sửa đổi này (cài đặt thành 200) cho tất cả các vỏ phụ tiếp theo và như vậy? Điều này có thể không?

Câu trả lời:


23

Một bản sao của môi trường truyền đến các vỏ con, vì vậy điều này hoạt động:

$ export MY_VAR=200
$ bash
$ echo $MY_VAR
200

nhưng vì nó là một bản sao, bạn không thể nhận được giá trị đó lên đến vỏ cha mẹ - ít nhất là bằng cách thay đổi môi trường.

Có vẻ như bạn thực sự muốn tiến thêm một bước, đó là tạo ra thứ gì đó hoạt động như một biến toàn cục, được chia sẻ bởi các vỏ "anh chị em" được khởi tạo tách biệt khỏi cha mẹ - như tab mới của bạn trong Gnome Terminal.

Hầu hết, câu trả lời là "bạn không thể, bởi vì các biến môi trường không hoạt động theo cách đó". Tuy nhiên, có một câu trả lời khác, đó là, bạn luôn có thể hack thứ gì đó. Một cách tiếp cận sẽ là ghi giá trị của biến vào một tệp, như ~/.myvar, và sau đó đưa nó vào ~/.bashrc. Sau đó, mỗi shell mới sẽ bắt đầu với giá trị được đọc từ tệp đó.

Bạn có thể tiến thêm một bước - đặt ~/.myvarở định dạng MYVAR=200, sau đó đặt PROMPT_COMMAND=source ~/.myvar, điều này sẽ khiến giá trị được đọc lại mỗi khi bạn nhận được lời nhắc mới. Nó vẫn không hoàn toàn là một biến toàn cầu được chia sẻ, nhưng nó bắt đầu hành động như vậy. Tuy nhiên, nó sẽ không kích hoạt cho đến khi lời nhắc trở lại, tùy thuộc vào những gì bạn đang cố gắng có thể là một hạn chế nghiêm trọng.

Và sau đó, tất nhiên, điều tiếp theo là tự động viết các thay đổi ~/.myvar. Điều đó phức tạp hơn một chút và tôi sẽ dừng lại ở thời điểm này, bởi vì thực sự, các biến môi trường không có nghĩa là một cơ chế giao tiếp giữa các lớp vỏ, và tốt hơn là chỉ cần tìm một cách khác để làm điều đó.


10
Tôi có thể nghe thấy tiếng rít vỏ dưới sự tra tấn

Ừ, xin lỗi. Đó là lý do tại sao tôi dừng lại. :)
mattdm

"đó là tạo ra thứ gì đó hoạt động như một biến toàn cầu" - Chà, thực sự, đó là những gì tôi đang cố gắng hoàn thành. ~ / .Myvar không đẹp, nhưng nó hoạt động. Bạn có đề nghị khác?
Ai đó vẫn sử dụng bạn MS-DOS

2
Chà, hãy lùi lại một chút. Tại sao bạn muốn một biến toàn cầu?
mattdm

1
@mattdm: Tôi có một số "quan liêu" mà tôi phải tuân theo. Một trong số đó là một loạt các mã tôi cần phải cam kết cùng với một nhận xét. Các mã này, hiện tại, trong một hệ thống phân cấp thư mục (home / user / dự án / projectcode / code1 / code2). Tôi đã tạo một hàm trích xuất code1 và code2 thành env vars (vì vậy khi tôi cần thực hiện một hoạt động, tôi chỉ cần gọi hàm bên trong thư mục với các mã), và khi chúng bắt đầu, tôi sử dụng vim và có một số hàm đọc những bình này và tự động bình luận Tôi nghĩ rằng sử dụng các tập tin cho đó có thể là một giải pháp.
Ai đó vẫn sử dụng bạn MS-DOS

13

Giả sử tôi có export MY_VAR=0trong ~/.bashrc.

Đó là sai lầm của bạn ngay tại đó. Bạn nên xác định các biến môi trường của mình ~/.profile, được đọc khi bạn đăng nhập. ~/.bashrcĐược đọc mỗi khi bạn khởi động shell; Khi bạn bắt đầu lớp vỏ bên trong, nó sẽ ghi đè MY_VAR. Nếu bạn đã không làm điều đó, biến môi trường của bạn sẽ lan truyền xuống dưới.

Để biết thêm thông tin về ~/.bashrcvs ~/.profile, thấy tôi trước bài viết trên này chủ đề .

Lưu ý rằng việc truyền lên trên (nhận giá trị được sửa đổi từ lớp con tự động được phản ánh trong vỏ cha) là không thể, dừng hoàn toàn.



3

Đừng sử dụng các biến môi trường. Sử dụng tập tin.

Để ngăn các quá trình giẫm đạp lên nhau khi cập nhật / đọc tệp, hãy sử dụng các tệp khóa và tập lệnh cập nhật mặt trước nhỏ có mục đích chỉ là cập nhật tệp với $ 1 nếu nó không bị khóa. Lockfiles được thực hiện bằng cách kiểm tra cơ bản nếu một tệp cụ thể tồn tại (/var/run/yourscript.lck) và nếu có, hãy đợi tệp biến mất trong một thời gian và thất bại nếu không. Ngoài ra, bạn phải xóa lockfile khi cập nhật tệp.

Hãy chuẩn bị để xử lý một tình huống trong đó tập lệnh không thể cập nhật tệp vì tệp đang bận.


8
Một mẹo: sử dụng các thư mục thay vì các tệp để khóa, bởi vì mkdirhoạt động như một thử nghiệm và tạo nguyên tử.
mattdm

1
Nếu các bạn muốn nói về việc khóa, thì bạn cũng có thể đang sử dụngflock(2)
Ehtesh Choudhury

@mattdm Tôi thấy rằng một liên kết tượng trưng ln -s dummy lockfile(ngay cả khi bị hỏng) cũng có thể hoạt động vì nó sẽ thất bại nếu liên kết tượng trưng đã tồn tại. Tôi tự hỏi một số cách để kiểm tra nếu điều đó thực sự an toàn 100%.
Sức mạnh Bảo Bình

1

Khi tôi vừa giải quyết câu hỏi này, tôi đã cố gắng giải quyết vấn đề cập nhật trạng thái (tức là các biến shell) từ các chuỗi con. Vì vậy, người ta có thể gán các biến, giả sử, bên trong một đường ống - và phép gán sẽ hiển thị rõ ràng cho cha mẹ.

Dĩ nhiên, điều này là không thể theo một cách đơn giản vì các phần riêng lẻ của một đường ống được thực thi trong các lớp con, được forklấy từ vỏ cha và do đó có bộ nhớ là chế độ xem sao chép trên bộ nhớ của cha mẹ. Tuy nhiên, tôi cho rằng giải pháp mỏng và trong suốt có thể khả thi dựa trên loại IPC " bộ nhớ dùng chung " .

Và tôi thậm chí đã tìm thấy một triển khai chính xác của thiết kế này ... nhưng nó ở Perl.

Thêm câu trả lời này dù sao cũng là một giải pháp có thể.

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.