Programmatically get the environment variables of another process? - winapi

I want to get the environment variables of process A from process B?
There is no relationship with A and B.
Not the System enviroment variables , but the enviroment variables that have been passed to the process!
In linux, or windows

In Linux you can do this by reading (or mmaping) /proc/[pid]/environ. From proc(5):
/proc/[pid]/environ
This file contains the environment for the process. The entries are separated by
null bytes ('\0'), and there may be a null byte at the end. Thus, to print out the
environment of process 1, you would do:
$ (cat /proc/1/environ; echo) | tr '\000' '\n'

The environment variables are shown in /proc/PID/environ:
$ cat /proc/19065/environ
DISPLAY=localhost:0.0SHELL=/bin/bashPWD=/home/phil...
check out this question.

Related

Why are spaces / newlines missing in interactive kubectl bash session

I've connected to a container inside my K8s cluster using:
kubectl -n <namespace> exec -ti <pod> -- bash
Next I'm looking at the content of files within the /proc virtual folder. So for looking at the environment variables defined for process with id 1, I do cat /proc/1/environ.
The problem is that the output is:
var1=valuevar2=valuevar3=value
instead of:
var1=value
var2=value
var3=value
The same thing happens for cat /proc/1/cmdline, as the output is
commandarg1arg2
instead of
command arg1 arg2
What's causing the newline and spaces to be omitted from the output, and how can it be corrected?
The pieces of the environment can not be separated by Newlines, because a Newline character could be part of the environment string itself. Imagine an environment variable with name X, where its value is AB\nY=Z. You could not distinguish it from the case that you have two variables, X and Y.
The heart of the environment managements are the system calls getenv and setenv, which are for instance present in the C language. The value of the environment variable is a C-string, i.e. a sequence of bytes terminated by a NUL-byte. In fact, NUL is the only value which is not permitted inside the value of an environment variable.
Hence what your cat shows you is the environment definitions, separated by a NUL-byte.

bash - expanding a string containing environment variable references

I'm using a bash shell. I have some values from my env that I want to extract and assign those values to a variable. I also need to split it at the = sign. What's the best utility for this using bash?
I basically need to create a string with these values stripping out the delimter as well:
echo -e "This is my $KEY and my profile is $PROFILE"
This is my Ru2cXJbgWQ0wdtKBGbS5/nVQvGo and my profile is foobar
Result:
-bash-4.1$ echo -e "This is my $KEY"
This is my
-bash-4.1$ env | grep KEY
KEY=Ru2cXJbgWQ0wdtKBGbS5/nVQvGo
Example:
$ env | grep KEY
KEY=Ru2cXJbgWQ0wdtKBGbS5/nVQvGo
$ env | grep DEFAULT_PROFILE
DEFAULT_PROFILE=foobar
To complement Anthony Geoghegan's helpful answer, which shows that Bash automatically represents environment variables as shell variables[1]:
In short: the fact that env | grep KEY returns KEY=Ru2cXJbgWQ0wdtKBGbS5/nVQvGo does NOT necessarily mean that an environment variable named KEY exists.
It is conceivable that the grep matches you're getting are matches of other environment variables' values or even the last line of multi-line variable name. Thanks, chepner.
While environment variable and values are typically single-line, they don't have to be. An example is Bash's own ability to export functions, whose typically multi-line definitions are exported as the values of specially named environment variables.
To verify that a given (Bash) shell variable is indeed based on an environment variable, use:
declare -p KEY # example with variable name 'KEY'
If KEY is indeed an environment variable, you'll see (using your example):
declare -x KEY="Ru2cXJbgWQ0wdtKBGbS5/nVQvGo"
Note the -x, which indicates an exported variable, which is synonymous with being an environment variable.
By contrast:
If KEY is a shell variable that isn't also an environment variable, the -x will be missing.
if KEY is neither a shell variable nor an environment variable, you'll see an error message.
anubhava, in a comment on the question, demonstrates a shell-independent way to test if an environment variable is defined:
printenv KEY # prints value of env. var. 'KEY'
An exit code of 0 tells you that the variable exists (even if it is has no value).
Note that printenv is an external utility that is not POSIX-compliant; it does, however, come with both Linux and BSD/OSX.
[1] Note that by using Bash's own string expansion (interpolation of double-quoted strings), what gets expanded is not only environment variable references, but also shell-only variable references. GNU utility envsubst, by contrast, allows you to restrict expansion to environment variables.
When Bash starts, each environment variable that it inherits is automatically created as a shell variable aka parameter. From the Bash man page:
When a program is invoked it is given an array of strings called the environment. This is a list of name-value pairs, of the form name=value.
The shell provides several ways to manipulate the environment. On invocation, the shell scans its own environment and creates a parameter for each name found, automatically marking it for export to child processes.
If KEY and PROFILE are environment variables, running
echo -e "This is my $KEY and my profile is $PROFILE"
should print the desired response.

Setting Jenkins Environment Variable value via evaluation of command

Anyone know how I can set the environment variable value based on unix terminal command in jenkins using inject variable or some other way. e.g CurrentBranch=ls /project/folder | grep my_name. This doesn't seem to work. I want this command,ls /project/folder | grep my_name, to be evaluated and the result should be set to CurrentBranch.
Some reason CurrentBranch variable value never gets evaluated but rather it always has a value as this: ls /project/folder | grep my_name
Anyone knows what I am doing wrong.
Thanks.
I don't think you can do this in a way so that it is available to any Jenkins task, which is written.
You can however write your Jenkins task so that all of them are executing a shell script, and then your question boils down to sourcing a suitable rc file (we use for instance zsh as a shell and have a special rc file just for Jenkins), and inside this file, you can set your environment in the usual way, i.e.
export $(ls /project/folder | grep my_name)
(Of course, grepping the output of ls in this way is not the best idea, but this is a different topic)
You can save CurrentBranch in a file called env and inject that file into your job using EnvFile Plugin
echo "CurrentBranch=`ls /project/folder | grep my_name`" > /tmp/env
In the jenkins job configuration, check the checkbox "Prepare an environment for the run" .
select below checkboxes
Keep Jenkins Environment Variables
Keep Jenkins Build Variables
in the "Script Content" section, run below command to create properties file
echo "CurrentBranch=`ls /project/folder | grep my_name`" > /tmp/jenkins_job.prop
then in "Properties File Path" section, give this properties file with full path name.
now CurrentBranch variable will be avialable through out the build and can be access using ${CurrentBranch} .

What is the meaning of "export" in Bash? [duplicate]

This question already has answers here:
What does the 'export' command do?
(3 answers)
Closed 7 years ago.
When I customize my environment, I add PATH=$PATH:$My-own-Path in file .bash_profile.
The tutorials tell me I should use this one: export PATH=$PATH:$My-own-Path
So, what is the difference?
To answer your exact specific question, in this particular case, there isn't any difference. Why?
Somewhere in the initialization process, the variable PATH has already been exported. A change in the variable's value which is already exported does not need another export; this is automatic. The processes fired hereafter will get the new value.
export makes the environment variable available to child processes
From man bash:
... The export and declare -x commands allow parameters and functions to be added to and deleted from the environment. If the value of a parameter in the environment is modified, the new value becomes part of the environment, replacing the old.
Also from man bash:
export [-fn] [name[=word]] ...
export -p
The supplied names are marked for automatic export to the environment of subsequently executed commands. If the -f option is given, the names refer to functions. If no names are given, or if the -p option is supplied, a list of names of all exported variables is printed. The -n option causes the export property to be removed from each name. If a variable name is followed by =word, the value of the variable is set to word. export returns an exit status of 0 unless an invalid option is encountered, one of the names is not a valid shell variable name, or -f is supplied with a name that is not a function.
Exported variables are available to other programs. Non-exported variables are not.
Example:
$ myVar=Foo # Create local
$ env | grep '^myVar='
$ export myVar # Export myVar to child process
$ env | grep '^myVar='
Foo
If you want to read more about this, check out export (GNU Bash manual).
Also, please note that non-exported variables will be available to subshells run with (...) and other similar notations:
$ thereVar=Bar
$ (echo $thereVar; echo $myVar; $myVar=testing; echo $myVar)
Bar
Foo
Testing
$echo $myVar
Foo
The subshell cannot affect variables in the parent shell.
For more information on subshells, please reference:
Command Grouping
Command Execution Environment
Every process has an area of memory called the environment block. In the environment block are environment variables. These look like ordinary variables, for example x=42.
In most shells (C shell is an exception) you move an ordinary variable into the environment block using export. That command can also create an environment variable without going through an intermediate stage. If the variable is already in the environment block then export will have no effect.
So why? When a new process is created, the default action is to copy various "core information" from parent to child. These include the current directory, the umask, the file descriptor table, the uid and gid, and the environment block.
Note that the child only gets a copy of the parent's environment block. The variable is not shared and cannot be passed back to the parent (except by using some other inter-process communication mechanism).
You can override this default behaviour using the env program, but this is rarely required.
So, if we set an environment variable in a shell script using export then all our child processes we create, when we call other programs, will get a copy of them. Some variable names are well-known and have a special meaning, and the PATH environment variable is probably the most important of those.
The PATH environment variable is used to find programs on UNIX/Linux. Directories in PATH are searched in left-right order each time we need to load a program. Bash also caches executable paths in a hash (KornShell calls them "tracked aliases").

What does the 'export' command do?

I happen to run some commands blindly, in order to get things done.
I started to work with Jenkins recently, and then I had to use this export command to run the Jenkins WAR archive. What does the export command do in general, and why do we need to run this command, while running Jenkins (after the Jenkins home is set)?
export in sh and related shells (such as Bash), marks an environment variable to be exported to child-processes, so that the child inherits them.
export is defined in POSIX:
The shell shall give the export attribute to the variables corresponding to the specified names, which shall cause them to be in the environment of subsequently executed commands. If the name of a variable is followed by = word, then the value of that variable shall be set to word.
I guess you're coming from a Windows background. So I'll contrast them (I'm kind of new to Linux too). I found a user's reply to my comment, to be useful in figuring things out.
In Windows, a variable can be permanent or not. The term environment variable includes a variable set in the cmd shell with the SET command, as well as when the variable is set within the Windows GUI, thus set in the registry, and becoming viewable in new cmd windows.
E.g., the documentation for the set command in Windows "Displays, sets, or removes environment variables. Used without parameters, set displays the current environment settings."
In Linux, set does not display environment variables. It displays shell variables which it doesn't call/refer to as environment variables. Also, Linux doesn't use set to set variables (apart from positional parameters and shell options, which I explain as a note at the end), only to display them and even then only to display shell variables. Windows uses set for setting and displaying, e.g., set a=5, but Linux doesn't.
In Linux, I guess you could make a script that sets variables on bootup, e.g., /etc/profile or /etc/.bashrc, but otherwise, they're not permanent. They're stored in RAM.
There is a distinction in Linux between shell variables, and environment variables. In Linux, shell variables are only in the current shell, and environment variables, are in that shell and all child shells.
You can view shell variables with the set command (though note that, unlike Windows, variables are not set in Linux with the set command).
set -o posix; set (doing that set -o posix once first, helps not display too much unnecessary stuff). So set displays shell variables.
You can view environment variables with the env command.
Shell variables are set with, e.g., just a = 5.
Environment variables are set with export. Export also sets the shell variable.
Here you see shell variable zzz set with zzz = 5, and see it shows when running set, but it doesn't show as an environment variable.
Here we see yyy set with export, so it's an environment variable. And see it shows under both shell variables and environment variables:
$ zzz=5
$ set | grep zzz
zzz=5
$ env | grep zzz
$ export yyy=5
$ set | grep yyy
yyy=5
$ env | grep yyy
yyy=5
$
Other useful QnAs:
https://unix.stackexchange.com/questions/176001/how-can-i-list-all-shell-variables
https://askubuntu.com/questions/26318/environment-variable-vs-shell-variable-whats-the-difference
Note: One point which elaborates a bit and is somewhat corrective to what I've written, is that, in Linux bash, 'set' can be used to set "positional parameters" and "shell options/attributes", and technically both of those are variables, though the man pages might not describe them as such.
But still, as mentioned, set won't set shell variables or environment variables). If you do set asdf then it sets $1 to asdf, and if you do echo $1 you see asdf.
If you do set a=5 it won't set the variable a, equal to 5. It will set the positional parameter $1 equal to the string of "a=5". So if you ever saw set a=5 in Linux it's probably a mistake unless somebody actually wanted that string a=5, in $1.
The other thing that Linux's set can set, is shell options/attributes. If you do set -o you see a list of them. And you can do for example set -o verbose, off, to turn verbose on (by the way, the default happens to be off, but that makes no difference to this). Or you can do set +o verbose to turn verbose off. Windows has no such usage for its set command.
In simple terms, environment variables are set when you open a new shell session. At any time if you change any of the variable values, the shell has no way of picking that change. That means the changes you made become effective in new shell sessions.
The export command, on the other hand, provides the ability to update the current shell session about the change you made to the exported variable. You don't have to wait until new shell session to use the value of the variable you changed.

Resources