Wie kann man Umgebungsvariablen zwischen Shells wie Globals teilen, die mit einer Master-PID zusammenhängen?

8

Daher muss ich Umgebungsvariablen zwischen Shells austauschen und sicherstellen, dass die Änderungen an den Variablen von allen Shells wie globalen Variablen sofort erkannt werden. Sie müssen sich jedoch auf eine Master-PID beziehen, damit zwei Shell-Skripte ausgeführt werden können, von denen jedes ein Master mit demselben globalen Variablennamen ist. Untergeordnete Elemente ändern nur die Variable, die sich auf ihre Master-PID bezieht.

Ich benutze bashfür Skripte.

Meine aktuellen Forschungen sind folgende:

Module, die
ich gelesen habe, könnte ich dafür ein Modulprojekt verwenden: http://modules.sourceforge.net/ , aber ich habe große Probleme damit, es scheint, es fehlen Beispiele? Auch "Module" ist ein zu allgemeines Wort, über das man nur schwer googeln kann, weil es sich mit vielen anderen Dingen vermischt. Nach einigen Wochen sind meine Hände immer noch leer.

Einfache Textquelldatei
Ich lese auch Ich sollte eine einfache Textdatei zum Speichern / Aktualisieren / Lesen von Variablen als Quellskriptdatei verwenden, flockum gleichzeitiges Schreiben zu vermeiden. Diesbezüglich gibt es jedoch Probleme, wie die gleichzeitige Änderung der Variablen um zwei Schalen.

Alternativ ist
mir bekannt, dass nach dem Lesen einer "globalen" Variablen durch die Shell dieser Wert beibehalten wird, bis ein weiterer Lesevorgang durchgeführt wird. und eine andere Shell kann es in der Zwischenzeit auch ändern ... Kann
eine sehr schnelle externe Anwendung einen solchen Speicher bereitstellen, und wir würden dann nicht versuchen, Umgebungsvariablen als globale Variablen zu verwenden? Aber ich vermute, dass jede SQL-Lösung zu langsam sein wird ...

Wassermann-Kraft
quelle
6
Das riecht nach einem XY-Problem . Umgebungsvariablen sind pro Prozess. Wenn Sie also systemweite Werte wünschen, verwenden Sie das falsche Tool. Welches Problem versuchen Sie zu lösen?
Gilles 'SO - hör auf böse zu sein'
Ich habe ein Master-Skript, das 5 untergeordnete Skripte mit xterm erzeugt, die jeweils unterschiedliche, aber verwandte Aufgaben ausführen. Sie alle müssen wissen, was im Master-Skript oder sogar untereinander vor sich geht, und in der Lage sein, sich zu melden oder dem Master bei Bedarf etwas vorzubereiten.
Wassermann Power
3
Ok, Umgebungsvariablen sind dafür völlig das falsche Werkzeug. Sie sollten wahrscheinlich etwas verwenden, das für die Interprozesskommunikation vorgesehen ist, z. B. Pipes. Lassen Sie den Master-Prozess entweder Änderungen an die untergeordneten Elemente senden (verhalten Sie sich jedoch blockierend, wenn die untergeordneten Elemente nicht antworten), oder lassen Sie die untergeordneten Elemente den Master regelmäßig nach Aktualisierungen abfragen. Eine von inotify überwachte Datei kann ebenfalls eine Option sein. Oder vielleicht sollten Sie ein einziges Programm haben, das an alle verschiedenen Terminals ausgegeben wird.
Gilles 'SO - hör auf böse zu sein'
Warum müssen Sie gleichzeitig schreiben? Was ist falsch daran, dass ein Prozess einige Millisekunden darauf wartet, dass der andere die Aktualisierung der Datei abschließt?
Psusi
@psusi Flock oder die Verwendung des ln -s realfile lockfileFail-Exit-Status tun genau das, was Sie gesagt haben: "Warte ein paar Mili ...". Ohne Sperre warten sie nicht auf den Versuch, ein Update durchzuführen. Dieser gleichzeitige Aktualisierungsversuch weist jedoch einen Fehler auf. Ein Prozess kann das neueste Update des anderen Prozesses überschreiben. Ich muss noch einen Testfall vorbereiten, um daran zu arbeiten ...
Aquarius Power

Antworten:

4

Sie können die Umgebung export -pmit .(den Befehl include) in eine Datei schreiben und in den anderen Instanzen regelmäßig zurücklesen . Wie Sie jedoch bemerken, ist das Ergebnis bei gleichzeitigen Änderungen nicht schön.

Wenn Sie möchten, dass Änderungen sofort weitergegeben werden, müssen Sie einen Wrapper um das integrierte exportElement verwenden, der die Änderungen auch auf die anderen Shells überträgt. Unter Linux können Sie das flockDienstprogramm verwenden.

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

Beachten Sie, dass Sie jedes Mal aufrufen müssen, global_exportwenn Sie einer exportierten Variablen einen neuen Wert zuweisen.

Das ist ziemlich ungeschickt. Es ist wahrscheinlich, dass es einen besseren Weg gibt, um Ihr Problem zu lösen. Der naheliegendste Weg ist, dass jeder Befehl, der diese Umgebungsvariablen verwendet, stattdessen eine Konfigurationsdatei liest.

Gilles 'SO - hör auf böse zu sein'
quelle
3

fishVerwenden Sie für die Shell Variablen mit universellem Gültigkeitsbereich :

set -U var value

Dies funktioniert natürlich nur über fishShells hinweg , die vom selben Benutzer ausgeführt werden.

Wenn Sie es an eine Master-PID binden möchten, fügen Sie es in den Variablennamen ein

set -U m${masterpid}var value
Stéphane Chazelas
quelle
2

Zusätzlich zu flockGiles 'Antwort würde ich etwas Ähnliches tun:

Registrieren Sie einen Signalhandler, um die Datei neu zu laden:

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

Eine Funktion zum Ausschreiben der Datei und zum Senden einer SIGUSR1Nachricht an alle Shells, um sie zum erneuten Laden der Datei zu benachrichtigen:

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

Öffnen Sie die Datei, aber machen Sie nichts damit. Dies ist nur so, dass der fuserdiese Shell signalisieren kann:

exec 3>>/path/to/env

Die Reihenfolge ist etwas wichtig. Zumindest exec ...muss das trap ...Teil nach dem Teil sein. Andernfalls könnten wir die Datei öffnen und dann vom fuserAnruf signalisiert werden , bevor wir unseren Signalhandler registriert haben.

HINWEIS: Code ist völlig ungetestet, aber das Prinzip steht.
HINWEIS 2: Dieser Beispielcode richtet sich an Bash.

Patrick
quelle
Interessant, also wo immer der Code ausgeführt wird, wird dieses eingeschlossene Signal sofort ausgeführt und die Umgebungsvariablen aktualisiert! Ich denke, in einem Code, der aus irgendeinem Grund davon abhängt, dass der env var-Wert derselbe ist, der zu Beginn der Funktion verwendet wurde, kann dies zu Problemen führen. Stattdessen kann mit Ihrem Code ein Boolescher Wert festgelegt werden erfordern, dass die env-Variablen an einem sicheren Punkt des Codes geladen werden (wie am Ende einer Schleife); wird das gleiche Ergebnis haben; Ich muss es versuchen, danke!
Wassermann Power
1

Ich möchte Sie zu diesem Zweck auf Named Pipes hinweisen . Hier ist ein gutes Beispiel .

Benannte Pipes werden mit dem folgenden Befehl erstellt:

mkfifo pipe_name

Sie können einfach schreiben, indem Sie:

echo "This text goes to the pipe" > pipe_name

Auf der anderen Seite können Sie aus der Pipe lesen als:

read line < pipe_name;
echo $line

Sie können mehrere Pipes erstellen, je nachdem, wie viele Shells sie kommunizieren sollen. Das Gute an Pipes ist, dass sie nicht nur Variablen sind. Sie können tatsächlich alle Daten zwischen den Prozessen übergeben. Sie können ganze Dateien und Textzeilen übergeben, was immer Sie möchten. In diesem Sinne können Sie Ihre Skripte erheblich vereinfachen. Ich kann mir vorstellen, dass Sie die Daten / Datei direkt übergeben können, wenn Ihre Variablen auf einen Speicherort von Daten oder eine Datei verweisen und das andere Skript sie lesen oder abrufen muss, ohne eine Variable zu benötigen.

Bichoy
quelle
cool! Interessant, wie das 1. Terminal gewartet hat Ich gebe den Lesebefehl auf dem anderen aus. Was ich anfangs sehe, ist, dass dies eine "Eins-zu-Eins" -Kommunikation ist und das 1. Terminal einfriert, bis das 2. die Pipe liest, und ich brauche auch eine "Viele zu Viele" -Kommunikation (viele können lesen, viele können gleichzeitig schreiben aber synchronisiert); aber in der Tat kann dieses neue Wissen nützlich sein, danke!
Wassermann Macht
1

Wenn ksh93 eine Option ist, gibt es definitiv eine Möglichkeit, das zu implementieren, was Sie wollen, mit Getter- und Setter-Disziplin-Funktionen, die den Variablenwert von / in einen gemeinsam genutzten Speicher abrufen / speichern.

Weitere Informationen finden Sie unter /programming/13726293/environment-variables-to-be-used-across-multiple-korn-ksh93-shell-scripts-get

Im Gegensatz zur ansonsten nützlichen Funktion für fishuniverselle Variablen haben Sie Zugriff auf die Implementierung, sodass Sie die Wertfreigabe auf eine Gruppe von Prozessen beschränken können, die über einen Mechanismus in Ihrem Anwendungsfall mit einer Master-PID verknüpft sind, während Sie einen einzelnen Namen für die Variable beibehalten.

jlliagre
quelle
Das ist sehr interessant, wie ich gesehen habe. Sie leiten einfach die Art und Weise um, wie es eingestellt wurde, und erhalten den Variablenwert. in der Tat habe ich mich nicht auf Bash beschränkt ... nun, gut, jetzt weiß ich davon; Ich frage mich, ob Bash eines Tages etwas Ähnliches haben könnte.
Aquarius Power
Es könnte schließlich. Disziplinfunktionen stehen auf der bashWunschliste. bashwird verwendet, um spätere Funktionen auszuwählen, die kshzuerst implementiert wurden.
Jlliagre
0

Berücksichtigen Sie Ihre Kommentare, dass Sie einen grundlegenden IPC zwischen Shell-Skripten wünschen. Ich würde nur in Dateien schreiben (mit einer Umbenennung für Atomizität)

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

Und lassen Sie die Leser regelmäßig ./myvars beziehen.

IPC ist beispielsweise mit Python und dem Multiprocessing-Modul viel einfacher.

Gabriel
quelle
0

Es gibt auch dieses Projekt ScriptEchoColor :

Es kann automatisch eine DB-Textdatei erstellen und für Sie verwalten. Beim ersten Ausführungsskript wird die BD-Datei erstellt, die anderen Skripte werden als eigene Datenbank mit dieser Datei verknüpft, um Variablenwerte zu bearbeiten, sodass beide Informationen austauschen können.

Ein einfaches Beispiel für die Freigabe dieser Dateien finden Sie im Beispielordner : secExplShareEnvVarsA.sh, secExplShareEnvVarsB.sh

Und auch dort ein synchronisierter (sicherer und konsistenter Lese- / Schreibzugriff) DB-Zugriff: secExplSyncedShareEnvVarsA.sh, secExplSyncedShareEnvVarsB.sh

Wassermann-Kraft
quelle