Jeśli zbadam /proc/1/environ
, zobaczę ciąg rozdzielany znakami zerowymi 1
zmiennych środowiskowych procesu . Chciałbym wprowadzić te zmienne do mojego obecnego środowiska. Czy jest na to łatwy sposób?
proc
Strona człowiek daje mi fragment, który pomaga być wydrukować każdą zmienną środowiskową w oparciu o wiersz po wierszu (cat /proc/1/environ; echo) | tr '\000' '\n'
. Pomaga mi to sprawdzić, czy zawartość jest poprawna, ale tak naprawdę muszę zrobić te źródła w mojej bieżącej sesji bash.
W jaki sposób mogę to zrobić?
źródło
. <(xargs -0 bash -c 'printf "export %q\n" "$@"' -- < /proc/nnn/environ)
, który również odpowiednio obsługuje zmienne z cudzysłowami."$@"
zamiast'{}'
. Dla tych, którzy zastanawiają się nad--
argumentem w poprawionej odpowiedzi: argumenty pozycyjnebash -c command_string
są przypisywane począwszy od$0
, a"$@"
rozszerza się o argumenty zaczynające się od$1
. Argument--
zostaje przypisany do$0
.W
bash
możesz wykonać następujące czynności. Będzie to działać dla wszystkich możliwych treści zmiennych i pozwoli uniknąćeval
:Spowoduje to zadeklarowanie odczytanych zmiennych jako zmiennych powłoki w uruchomionej powłoce. Aby zamiast tego wyeksportować zmienne do działającego środowiska powłoki:
źródło
W tej odpowiedzi zakładam system, w którym
/proc/$pid/environ
zwraca środowisko procesu o określonym PID, z bajtami zerowymi między definicjami zmiennych. ( Więc Linux, Cygwin lub Solaris (?) ).Zsh
(Całkiem proste, jak mówi zsh: przekierowanie wejściowe bez polecenia
<FILE
jest równoważnecat FILE
. Wyjście zastępowania polecenia podlega rozszerzeniu parametru z flagamips:\000:
oznaczającymi „podziel na bajty zerowe” i@
„jeśli wszystko jest w podwójnych cudzysłowach, to potraktuj każdy element tablicy jako osobne pole ”(uogólnianie"$@"
).)Bash, mksh
(W tych powłokach pusty separator przekazywany do separatorów
read
powoduje, że puste bajty są zerowe. UżywamPWD
jako nazwy zmiennej tymczasowej, aby uniknąć zablokowania innej zmiennej, która mogłaby zostać zaimportowana. Chociaż technicznie można również importowaćPWD
, pozostanie ona ustawiona tylko do następnycd
.)POSIX
Przenośność POSIX nie jest tak interesująca w przypadku tego pytania, ponieważ dotyczy tylko systemów, które mają
/proc/PID/environ
. Pytanie brzmi: co obsługuje Solaris sed - czy też Solaris/proc/PID/environ
go nie wykorzystał, ale jestem daleko w tyle za funkcjami Solaris, więc może teraz. W Linuksie narzędzia GNU i BusyBox są zerowo bezpieczne, ale z zastrzeżeniami.Jeśli nalegamy na przenośność POSIX, żadne z narzędzi tekstowych POSIX nie jest wymagane do obsługi bajtów zerowych, więc jest to trudne. Oto rozwiązanie, które zakłada, że awk obsługuje bajt zerowy jako separator rekordów (nawk i gawk robią, podobnie jak awy BusyBox, ale mawk nie).
BusyBox awk (który jest wersją powszechnie spotykane na wbudowanych systemów Linux) obsługuje NULL bajty ale nie ustawienie
RS
się"\0"
wBEGIN
bloku, a nie linia składnia polecenia powyżej; jednak obsługuje-v 'RS="\0"'
. Nie badałem dlaczego, to wygląda na błąd w mojej wersji (Debian wheezy).(Zawiń wszystkie
wierszerekordów rozdzielonych zerami w pojedyncze cudzysłowy"\047"
, po ucieczce pojedynczych cudzysłowów w wartościach.)Ostrzeżenia
Uważaj, aby którykolwiek z nich mógł próbować ustawić zmienne tylko do odczytu (jeśli twoja powłoka ma zmienne tylko do odczytu).
źródło
Chodziłem z tym po kółku. Byłem sfrustrowany przenośnością zerowych bajtów. Nie podobało mi się to, że nie było niezawodnego sposobu na obsłużenie ich w skorupce. Więc szukałem dalej. Prawda jest taka, że znalazłem kilka sposobów, aby to zrobić, z których tylko kilka zostało odnotowanych w mojej drugiej odpowiedzi. Ale rezultatem były co najmniej dwie funkcje powłoki, które działają w ten sposób:
Najpierw porozmawiam o
\0
rozgraniczeniu. To jest naprawdę łatwe do zrobienia. Oto funkcja:Zasadniczo
od
pobierastdin
i zapisuje dostdout
każdego otrzymanego bajtu w systemie szesnastkowym po jednym w wierszu.Założę się, że możesz zgadnąć, co jest
\0null
, prawda? Tak napisane jest łatwe w obsłudze z każdymsed
.sed
po prostu zapisuje dwa ostatnie znaki w każdej linii, aż napotka zero, w którym to miejscu zastępuje nowe znaki pośrednieprintf
kodem przyjaznego formatu i wypisuje ciąg. Wynikiem jest\0null
rozdzielona tablica ciągów bajtów szesnastkowych. Popatrz:Przetokowałem powyższe, aby
tee
można było zobaczyć zarówno wynik działania polecenia, jak i wynikprintf
jego przetwarzania. Mam nadzieję, że zauważysz, że podpowłoka faktycznie nie jest cytowana, aleprintf
nadal dzieli się tylko na\0null
ograniczniku. Popatrz:Brak cytatów na temat tego rozszerzenia - nie ma znaczenia, czy go zacytujesz, czy nie. Wynika to z tego, że wartości zgryzu są
\n
rozdzielane osobno, z wyjątkiem jednej linii ewline generowanej za każdym razem, gdysed
drukuje łańcuch. Podział słów nie ma zastosowania. I to sprawia, że jest to możliwe:Powyższa funkcja używa
_zedlmt
albo${pcat}
do przygotowanego strumienia kodu bajtowego do pozyskiwania środowiska dowolnego procesu, który można znaleźć w/proc
, lub bezpośrednio do.dot
${psrc}
tego samego w bieżącej powłoce lub bez parametru, aby wyświetlić przetworzone wyjście tego samego na terminalu, takie jakset
lubprintenv
będzie. Wszystko czego potrzebujesz to$pid
- zrobi każdy czytelny/proc/$pid/environ
plik.Używasz go w ten sposób:
Ale jaka jest różnica między człowiekiem przyjaznym a zasobnym ? Różnica polega na tym, że ta odpowiedź różni się od wszystkich tutaj - w tym mojej drugiej. Każda inna odpowiedź zależy w jakiś sposób od cytowania powłoki w celu obsłużenia wszystkich przypadków krawędzi. Po prostu nie działa tak dobrze. Proszę uwierz mi - SPRÓBOWAŁEM. Popatrz:
ŻADNA liczba funky znaków lub zawartych cytatów nie może tego zepsuć, ponieważ bajty dla każdej wartości nie są obliczane aż do momentu, gdy zawartość jest pobierana. Wiemy już, że przynajmniej raz działała jako wartość - nie ma tu potrzeby analizy składni ani cytowania, ponieważ jest to kopia bajt po bajcie oryginalnej wartości.
Ta funkcja najpierw ocenia
$var
nazwy i czeka na zakończenie kontroli, zanim.dot
sourcing dokona tego tutaj, podając go deskryptorowi pliku 3. Zanim zacznie źródła, tak to wygląda. Jest głupi. I przenośny POSIX. Cóż, przynajmniej obsługa \ 0null jest przenośna POSIX - system plików / process jest oczywiście specyficzny dla Linuksa. I dlatego są dwie funkcje.źródło
Używanie
source
i proces zastępowania :Wkrótce:
Używanie
eval
i zastępowanie poleceń :sed
Połączenie może być zastąpione przezawk
wywołanie:Ale nie zapominaj, że nie usuwa żadnych zmiennych środowiskowych, które nie są w pid 1.
źródło
Warto zauważyć, że procesy mogą mieć zmienne środowiskowe, które nie są poprawnymi zmiennymi Bash / Sh / * sh - POSIX zaleca, ale nie wymaga, aby zmienne środowiskowe miały identyczne nazwy
^[a-zA-Z0-9_][a-zA-Z0-9_]*$
.Aby wygenerować listę zmiennych kompatybilnych z powłoką ze środowiska innego procesu, w Bash:
Podobnie, aby je załadować:
Ten problem pojawia się tylko sporadycznie, ale kiedy ...
źródło
Myślę, że to przenośny POSIX:
Ale @Gilles ma rację -
sed
prawdopodobnie poradzi sobie z zerami, ale może nie. Więc jest to (Naprawdę tak myślę tym razem) przenośna metoda POSIX:Jeśli jednak masz GNU
sed
, musisz tylko:Cóż, POSIX jest przenośny, z wyjątkiem tego,
/dev/...
który nie jest określony, ale można oczekiwać, że ta składnia będzie zachowywać się tak samo w większości Unices.Teraz, jeśli ma to coś wspólnego z twoim drugim pytaniem , możesz użyć go w następujący sposób:
Dokument tutaj jest niezwykle pomocny, ponieważ zapobiega przykręcaniu powłoki przez cytowanie, które tak ciężko pracujemy w podpowłoce, a także zapewnia nam niezawodną ścieżkę do pliku
.dot
źródłowego zamiast, znowu, podpowłoki lub powłoki zmienna. Inni tutaj używają bashizmu, który działa w ten sam sposób - tyle że zdecydowanie jest anonimowy, podczas gdy POSIX określa tylko dokumentację tutaj, więc może to być dowolny typ pliku, choć w praktyce jest to zwykle plik. ( z drugiej strony używa anonimowości dla dokumentów tutaj)<(process substitution)
|pipe
iohere
temp
dash,
|pipes
. Jednak niefortunną rzeczą w zastępowaniu procesów jest to, że zależy to również od powłoki - co może być szczególnie denerwujące, jeśli pracujeszinit
.Działa to
|pipes
oczywiście również, ale w końcu tracisz środowisko, gdy|pipe's
stan wyparowuje wraz z jego podpowłoką. To znowu działa:Sama
sed
instrukcja działa, utrzymując każdą linię w pamięci, aż dojdzie do ostatniej, w tym czasie wykonuje globalną obsługę zastępowania, cytowanie i wstawianie nowych linii, gdzie jest to właściwe, przez zakotwiczenie na zerach. Naprawdę dość proste.Na
dash
zdjęciu zobaczysz, że zdecydowałem się uniknąć \ bałaganu i dodałemGNU
konkretną-r
opcję dosed
. Ale to tylko dlatego, że mniej było pisać. Działa to w obie strony, jak widać nazsh
obrazku.Oto
zsh
:A oto
dash
robi to samo:Nawet ucieczki terminali przechodzą bez szwanku:
źródło
/proc/PID/environ
. Więc pytanie brzmi, co obsługuje Solaris sed - lub czy Solaris ma/proc/PID/environ
, nie przywykł, ale jestem w pewnym sensie za zakrętem na temat funkcji Solaris, więc może dziś).sed
jest wymagany do obsługi ascii w systemie szesnastkowym, z czego bajt zerowy to jeden. Poza tym właściwie pomyślałem, czy nadal jest to o wiele łatwiejszy sposób.\xNN
składnia nie jest wymagana w POSIX, nawet\OOO
składni ósemkowej (w ciągach C i w awk, tak, ale nie w wyrażeniach regularnych sed)./proc/PID/environ
przecież (ma kilka innych wpisów podobnych do Linuksa/proc/PID
, ale nie maenviron
). Zatem przenośne rozwiązanie wcale nie musi wykraczać poza narzędzia Linux, co oznacza GNU sed lub BusyBox sed. Oba obsługują\x00
wyrażenia regularne, więc kod jest tak przenośny, jak to konieczne (ale nie POSIX). Jest to jednak zbyt skomplikowane.źródło