Skip to content

Instantly share code, notes, and snippets.

  • Star 20 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
Star You must be signed in to star a gist
What would you like to do?
inherit environment variables from PID 1

You can inherit the environment variables from PID 1 by iterating over the list of null-terminated strings in /proc/1/environ, parsing the first characters up to the first = as the variable name, setting the remaining value as that variable, and exporting it.

The Code Snippet

This works with multiline environment variables, and environment variables with arbitrary values, like strings, including = or JSON blobs.

Paste this in your current terminal session to inherit the environment variables from PID 1:

while read -r -d $'\0' EVAR ; do
  evar_name="$(cut -d'=' -f1 <<< "$EVAR" | head -n1)"
  declare $evar_name="${EVAR#${evar_name}=}"
  export "$evar_name"
done < /proc/1/environ

Note: This only works with bash since it uses declare. But the advantage is that the values never need to pass through any serialization boundary (like they do when saving to a file, or printing export statements to eval them, or various other techniques that don't work for all corner cases )

See also: Unix StackExchange: "How do I source another process's environment variables?"


scenario: You popped a reverse shell in your CI runner and you want to manually run some of your CI scripts. But your SSH session into the CI runner didn't inherit all the environment variables that are available to the actual CI runner. These are set by the CI platform to be environment variables in PID 1.

You can see them with:

cat /proc/1/environ

This file is a concatenation of null-terminated strings of variable assignments. You can reveal the non-printing characters:

cat -vet /proc/1/environ

This is equivalent to cat -v -vE -vT - it will show $ for newlines, ^I for tab characters, and will show non-printing characters, like the separator ^@ (null byte aka $'\0'). Note: you probably do not want to parse this output. It's just useful for debugging and seeing where the separators are.

Copy link

chfritz commented Jan 21, 2023

Why not just export $(sudo cat /proc/1/environ | tr '\0' '\n' | xargs) ? Is that one of the other techniques you were referring to that fails in some cases?

Copy link

khirbat commented Jan 21, 2023

@chfritz This fails on whitespace, as this quick experiment shows. SSH_CONNECTION=... 63882 22 is the culprit here.

pi@4b8:~ $ export $(xargs -0 </proc/$$/environ)
-bash: export: `63882': not a valid identifier
-bash: export: `22': not a valid identifier
-bash: export: `63882': not a valid identifier
-bash: export: `': not a valid identifier
-bash: export: `22': not a valid identifier

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment