2010-08-25 10 views
15

Próbuję przedzierać się przez inne środowiska procesów, aby uzyskać określony env var.Używanie sed, aby uzyskać env var z/proc/*/environ dziwactwa z x00

Więc starałem się sed polecenia jak:

sed -n "s/\x00ENV_VAR_NAME=\([^\x00]*\)\x00/\1/p" /proc/pid/environ

Ale ja dostaję jako wyjście pełny plik środo. Gdybym zastąpić \ 1 z tylko statycznym ciąg, otrzymuję ten ciąg plus cały plik środo:

sed -n "s/\x00ENV_VAR_NAME=\([^\x00]*\)\x00/BLAHBLAH/p" /proc/pid/environ

powinien po prostu być coraz „blahblah” w poprzednim przykładzie. Tak się nie stanie, jeśli pozbędę się znaków zerowych i użyję innego zestawu danych testowych.

to doprowadzić mnie do próby przekształcenia \ x00 \ x01 do tych, które nie wydają się działać:

cat /proc/pid/environ | tr '\000' '\001' | sed -n "s/\x01ENV_VAR_NAME=\([^\x01]*\)\x01/\1/p"

jestem brakuje czegoś proste o sed tutaj? Czy powinienem po prostu trzymać się tego obejścia?

Odpowiedz

12

Można przetwarzać listy z gawk, ustawienie separatora rekordu do \0 i separator pól do =:

gawk -v 'RS=\0' -F= '$1=="ENV_VAR_NAME" {print $2}' /proc/pid/environ 

Albo można użyć read w pętli czytać każdy NUL rozdzielany linię. Na przykład:

while read -d $'\0' ENV; do declare "$ENV"; done < /proc/pid/environ 

echo $ENV_VAR_NAME 

(Czy to w sub-shell, aby uniknąć przebijania własnego środowiska.)

+0

Rozwiązuje to również mój problem z omacku ​​z pasującymi pierwszy env var w pliku, który nie ma \ x01 przed nim. Wielkie dzięki. –

+0

Uratowałeś mi dzień. Myślę, że jest to jedyny sposób przekazania wartości zmiennej dynamicznej do usługi uruchamianej systemd. –

+0

'awk' nie działa, jeśli wartość zmiennej zawiera' = '? np .: 'awk -v 'RS = \ 0' -F = '$ 1 ==" LS_COLORS "{print $ 2}' Jasen

2

do jakiegoś powodu sed nie pasuje \ 0 z .

% echo -n "\00" | xxd 
0000000: 00          . 
% echo -n "\00" | sed 's/./a/g' | xxd 
0000000: 00          . 
% echo -n "\01" | xxd     
0000000: 01          . 
% echo -n "\01" | sed 's/./a/g' | xxd 
0000000: 61          a 

Rozwiązanie: nie używaj sed ani nie stosuj obejścia.

+0

wielkie kroki rozwiązywania problemów, dziękuję. –

31

Wiele programów napisanych w C ma tendencję do zawierania ciągów z wbudowanymi NUL-ami, ponieważ NUL kończy łańcuch w stylu C. Chyba że specjalnie napisany, żeby sobie z tym poradzić.

I Proces/proc/*/środo w linii poleceń z xargs:

xargs -n 1 -0 < /proc/pid/environ 

To daje jeden var env każdym wierszu. Bez polecenia xargs po prostu odbija argument. Możesz wtedy łatwo używać grep, sed, awk, itp., Poprzez instalację do niego.

xargs -n 1 -0 < /proc/pid/environ | sed -n 's/^ENV_VAR_NAME=\(.*\)/\1/p' 

Używam tego wystarczająco często, że mam dla niego funkcję powłoki:

pidenv() 
{ 
    xargs -n 1 -0 < /proc/${1:-self}/environ 
} 

Daje to środowisko konkretnego PID lub siebie jeśli żaden argument nie jest dostarczany.

+0

bardzo fajne. Nigdy bym nie pomyślał o używaniu xargs w takiej roli. Jednak na początku tego typu rozwiązania uniknąłem, ponieważ chciałem uniknąć problemów z wartościami env var z \ n zawartymi w nich. –

+0

xargs pozwala w łatwy sposób obsługiwać wartości wielowierszowe, uruchamiając skrypt lub program dla każdego argumentu, zamiast tylko go echo. W ten sposób każdy argument może być przetwarzany niezależnie wiedząc, że za każdym razem, gdy skrypt jest wywoływany, jest prezentowany z jedną wartością niezależnie od liczby wierszy w nim zawartych. – camh

+0

Nice! Xargs ma również miły efekt uboczny przycinania białych znaków. echo "foo" | xargs | wc -C# => 4 – ppetraki

10
cat /proc/PID/environ | tr '\0' '\n' | sed 's/^/export /' ; 

następnie skopiuj i wklej w razie potrzeby.

+0

ten kod zawodzi w przypadku zmiennych zawierających znaki nowej linii - ale jest krótki. – Jasen

4

Pomimo bardzo stare i odpowiedział na pytanie, dodaję jeden bardzo prosty oneliner, prawdopodobnie prostszy do uzyskania tekstu wyjściowego i dalszego przetwarzania:

strings /proc/$PID/environ 
+0

Jest to poważnie niedoceniana odpowiedź, sprawia, że ​​bardzo łatwo można ją przekierować do '| grep -E '^ (ENV_NAME) =' ' –