Làm thế nào để chia sẻ các biến môi trường giữa các shell như toàn cầu liên quan đến pid chính?


8

Vì vậy, tôi cần chia sẻ các biến môi trường giữa các shell và rằng các thay đổi trên các biến sẽ được nhận ra kịp thời bởi tất cả các shell, như các biến toàn cục. Nhưng chúng phải liên quan đến một PID chính, vì vậy tôi có thể có 2 tập lệnh shell đang chạy, mỗi tập lệnh là một chủ có cùng tên biến toàn cục và nó sẽ chỉ thay đổi biến liên quan đến PID chính của chúng.

Tôi sử dụng bashcho kịch bản.

Các nghiên cứu hiện tại của tôi là:

Các mô-đun
tôi đọc tôi có thể sử dụng dự án mô-đun cho điều đó: http://modules.sourceforge.net/ , nhưng tôi gặp khó khăn lớn khi cố gắng thực hiện, có vẻ như thiếu ví dụ? còn "mô-đun" là một từ quá chung chung, rất khó để tìm hiểu về google vì trộn lẫn với nhiều thứ khác. Sau vài tuần, tay tôi vẫn trống rỗng

Tệp nguồn văn bản đơn giản
Tôi cũng đọc Tôi nên sử dụng một tệp văn bản đơn giản để lưu trữ / cập nhật / đọc các biến từ, như một tệp tập lệnh nguồn, sử dụng flockquá để tránh ghi đồng thời. Nhưng có những vấn đề liên quan đến việc đó, như thay đổi đồng thời biến 2 đồng thời.

Ngoài ra,
tôi biết rằng sau khi một biến "toàn cầu" được đọc bởi shell, nó sẽ giữ giá trị đó cho đến khi một lần đọc khác được thực hiện; và một shell khác có thể thay đổi nó theo nghĩa trung bình trong khi quá
có thể là một ứng dụng bên ngoài rất nhanh có thể cung cấp lưu trữ như vậy và chúng ta sẽ không thử sử dụng các biến môi trường như toàn cầu? nhưng tôi đoán là bất kỳ giải pháp SQL nào cũng sẽ quá chậm


6
Điều này có mùi giống như một vấn đề XY . Biến môi trường là mỗi quy trình, vì vậy nếu bạn muốn các giá trị toàn hệ thống, bạn đang sử dụng công cụ sai. Vấn đề gì bạn đang cố gắng giải quyết?
Gilles 'SO- ngừng trở nên xấu xa'

Tôi có một tập lệnh chính sinh ra 5 tập lệnh con với xterm, mỗi tập lệnh thực hiện các tác vụ khác nhau nhưng có liên quan; tất cả họ cần biết những gì đang diễn ra trên kịch bản chính, hoặc thậm chí lẫn nhau, và cũng có thể báo cáo lại, hoặc chuẩn bị một cái gì đó cho chủ nếu cần.
Sức mạnh Bảo Bình

3
Ok, biến môi trường hoàn toàn là công cụ sai cho điều đó. Có lẽ bạn nên sử dụng một cái gì đó dành cho giao tiếp giữa các quá trình, chẳng hạn như đường ống. Hoặc có quy trình phát sóng chính thay đổi cho trẻ em (nhưng hành vi chặn nếu trẻ không phản hồi) hoặc để trẻ định kỳ truy vấn chủ để cập nhật. Một tập tin được xem bởi inotify cũng có thể là một tùy chọn. Hoặc có lẽ bạn nên có một chương trình duy nhất xuất ra tất cả các thiết bị đầu cuối khác nhau.
Gilles 'SO- ngừng trở nên xấu xa'

Tại sao bạn cần viết đồng thời? Có gì sai với một quá trình chờ vài mili giây để quá trình kia hoàn tất cập nhật tệp?
psusi

@psusi đàn hoặc sử dụng ln -s realfile lockfiletrạng thái thoát thất bại sẽ chỉ làm những gì bạn nói "đợi một vài mili ...", không có khóa họ sẽ không chờ đợi để cập nhật; nhưng nỗ lực cập nhật đồng thời đó có một lỗ hổng; một quy trình có thể ghi đè lên bản cập nhật mới nhất của quy trình khác, tôi vẫn cần chuẩn bị một trường hợp thử nghiệm để làm việc với nó ...
Aquarius Power

Câu trả lời:


4

Bạn có thể ghi môi trường vào một tệp với export -pvà đọc lại định kỳ trong các trường hợp khác với .(lệnh bao gồm). Nhưng như bạn lưu ý, nếu có sửa đổi đồng thời, kết quả sẽ không đẹp.

Nếu bạn muốn sửa đổi để lan truyền ngay lập tức, bạn sẽ phải sử dụng một trình bao bọc xung quanh phần exportdựng sẵn cũng truyền các thay đổi cho các trình bao khác. Trên Linux, bạn có thể sử dụng flocktiện ích.

global_export () {
  {
    flock 0
    . /path/to/env
    [ $# -eq 0 ] || export "$@"
    export -p >/path/to/env
  } </path/to/env
}

Lưu ý rằng bạn sẽ cần gọi global_exportbất cứ khi nào bạn gán giá trị mới cho biến đã xuất.

Điều này khá vụng về. Có khả năng là có một cách tốt hơn để giải quyết vấn đề của bạn. Cách rõ ràng nhất là có bất kỳ lệnh nào đang sử dụng các biến môi trường đó đọc các tệp cấu hình thay thế.


3

Với fishshell, sử dụng các biến có phạm vi phổ quát :

set -U var value

Tất nhiên, điều đó chỉ hoạt động trên các fishshell được điều hành bởi cùng một người dùng.

Nếu bạn muốn buộc nó vào pid chính , hãy đưa nó vào tên biến

set -U m${masterpid}var value

2

Ngoài việc chỉ sử dụng flocktừ câu trả lời của Giles, tôi sẽ làm một cái gì đó tương tự như sau:

Đăng ký một trình xử lý tín hiệu để tải lại tập tin:

reload_env() {
 flock -s 3
 . /path/to/env
 flock -u 3
}
trap reload_env USR1

Một chức năng để viết ra tệp và gửi SIGUSR1đến tất cả các shell thông báo cho chúng để tải lại tệp:

export_env() {
 flock 3
 export -p >/path/to/env
 flock -u 3
 fuser -k -USR1 /path/to/env
}

Mở tệp, nhưng không làm gì với nó. Đây chỉ là để fusercó thể báo hiệu lớp vỏ này:

exec 3>>/path/to/env

Thứ tự có phần quan trọng. Ít nhất là exec ...một phần phải sau trap ...phần. Nếu không, chúng tôi có thể mở tệp và sau đó nhận được tín hiệu bằng fusercuộc gọi trước khi chúng tôi đăng ký xử lý tín hiệu.

LƯU Ý: Mã hoàn toàn chưa được kiểm tra, nhưng nguyên tắc đứng.
CHÚ THÍCH 2: Mã ví dụ này được nhắm mục tiêu tại bash.


Thật thú vị, vì vậy bất cứ nơi nào mã đang thực thi, tín hiệu bị mắc kẹt đó sẽ được thực thi kịp thời, cập nhật các biến môi trường! Tôi nghĩ trong một mã mà vì bất kỳ lý do nào phụ thuộc vào giá trị var của env giống như khi đặt hàm, có thể gây ra một số rắc rối tho .. nhưng, thay vào đó, một boolean có thể được đặt với mã của bạn, để yêu cầu các lọ env được tải trong điểm an toàn của mã (như cuối vòng lặp); sẽ có kết quả tương tự; Tôi phải thử một lần, thx!
Sức mạnh Bảo Bình

1

Tôi muốn chỉ cho bạn các ống được đặt tên cho mục đích này. Đây là một ví dụ gọn gàng để xem xét.

Các ống được đặt tên được tạo bởi lệnh:

mkfifo pipe_name

Bạn chỉ có thể viết thư cho nó bằng cách:

echo "This text goes to the pipe" > pipe_name

Mặt khác, bạn có thể đọc từ ống như:

read line < pipe_name;
echo $line

Bạn có thể tạo một số đường ống dựa trên số lượng vỏ bạn muốn chúng giao tiếp. Những điều tốt về đường ống là chúng không chỉ là biến. Bạn thực sự có thể vượt qua bất kỳ dữ liệu giữa các quá trình. Bạn có thể vượt qua toàn bộ tập tin, dòng văn bản, bất cứ điều gì bạn muốn. Tôi tin rằng, với suy nghĩ này, bạn có thể đơn giản hóa các kịch bản của mình rất nhiều. Tôi có thể tưởng tượng, nếu các biến của bạn trỏ đến một vị trí của dữ liệu hoặc tệp và tập lệnh khác sẽ phải đọc hoặc truy xuất nó, bạn có thể trực tiếp truyền dữ liệu / tệp mà không cần đến biến.


mát mẻ! Thật thú vị khi thiết bị đầu cuối thứ nhất chờ đợi tôi phát lệnh đọc trên đầu kia. Những gì tôi thấy ban đầu là đây là một giao tiếp "một đối một" và nó đóng băng thiết bị đầu cuối thứ 1 cho đến khi thứ 2 đọc được đường ống và tôi cũng cần một giao tiếp "Nhiều đến nhiều" (nhiều người có thể đọc, nhiều người có thể viết, đồng thời nhưng đồng bộ); nhưng thực sự kiến ​​thức mới này có thể hữu ích thx!
Sức mạnh Bảo Bình

1

Nếu ksh93 là một tùy chọn, chắc chắn có một cách để thực hiện những gì bạn muốn với các hàm kỷ luật getter và setter sẽ truy xuất / lưu trữ giá trị biến từ / đến một bộ lưu trữ được chia sẻ.

Xem /programming/13726293/envir-variables-to-be-use-across-multipl-korn-ksh93-shell-scripts-get để biết chi tiết

Không giống như fishtính năng biến phổ biến hữu ích khác, bạn có quyền truy cập vào việc triển khai để bạn có thể hạn chế chia sẻ giá trị cho một nhóm các quy trình, được liên kết với pid chính thông qua một số cơ chế trong trường hợp sử dụng của bạn, trong khi vẫn giữ một tên duy nhất cho biến.


Điều đó rất thú vị như tôi đã thấy, bạn chỉ cần chuyển hướng cách đặt và nhận giá trị biến; thực sự tôi đã không hạn chế cho bash ... tốt, bây giờ tôi biết về nó; Tôi tự hỏi liệu bash có thể có thứ gì đó tương tự vào một ngày nào đó không ..
Sức mạnh của Bảo Bình

Nó có thể cuối cùng. Chức năng kỷ luật là trong bashdanh sách mong muốn. bashsử dụng để chọn các tính năng sau được kshthực hiện đầu tiên.
jlliagre

0

Có tính đến ý kiến ​​của bạn, rằng bạn muốn IPC cơ bản giữa các tập lệnh shell. Tôi sẽ chỉ viết vào các tập tin (với một sự đổi tên cho nguyên tử)

varf=$(mktemp ./myvars.XXXXXX)
echo myvar=newval > $varf
mv -T -- $varf ./myvars

Và có nguồn độc giả ./myvars định kỳ.

IPC dễ dàng hơn nhiều, ví dụ, Python và mô đun đa xử lý.


0

Ngoài ra còn có dự án ScriptEchoColor này :

Nó có thể tự động tạo và quản lý cho bạn một tệp văn bản DB. Trong tập lệnh chạy đầu tiên, tệp BD sẽ được tạo, các tập lệnh khác sẽ liên kết với tệp đó dưới dạng DB riêng để thao tác các giá trị biến và do đó, cả hai đều có thể trao đổi thông tin.

Một ví dụ chia sẻ đơn giản với các tệp này tại thư mục ví dụ : secExplShareEnvVarsA.sh, secExplShareEnvVarsB.sh

Và một truy cập DB được chia sẻ đồng bộ (an toàn và nhất quán) cũng có: secExplSyncedShareEnvVarsA.sh, secExplSyncedShareEnvVarsB.sh

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.