environment variable included in printenv but can't echo them - bash

I have a problem that is puzzling me.
I am inside a docker container on a ubuntu machine using a bash shell.
I want to check if the environment variable called "ENVIRONMENT" used by my code is properly set.
When I do "printenv" I can see the variables:
root#863cf368a72d:/data-cron# printenv
ENVIRONMENT = staging
PYTHON_VERSION=3.9.5
HOME=/root
(etc, can't disclose the full details of the environment variables of this product).
Now, if I do:
root#863cf368a72d:/data-cron# echo $ENVIRONMENT
I get nothing! But if I try with another variable:
root#863cf368a72d:/data-cron# echo $HOME
I get the right answer:
/root
Needless to say, my code doesn't work because the variable "ENVIRONMENT" is set to None
Does anyone have any idea? I am puzzled by the mismatch between printenv and echo, I never saw that happening. Thanks in advance

According to what you posted, you don't have an environment variable named ENVIRONMENT, but one named ENVIRONMENT , as you can see from the space in front of the equal sign. Environment variables can be any string, so this variable is not valid.
While you can't set an environment variable with such an odd name (containing a space) from the shell, you can do so from most other applications. Try to grep for where you have a such a string in your configuration. I would not be surprised if this is found in your docker configuration.
BTW, if you want to see exactly what's in a similarily named environment variable, you could also do a
xxd <(printenv|grep ENVIRONMENT)
which should show you byte by byte the name of the variable, including possible unprintable characters.

Related

Can't get environment variable from /etc/profile in GoLang

I've set some environment variables in /etc/profile, I can access them from bash, but for some reason I cant get them from Go.
/etc/profile:
...
TEST_ENV=test_me
I can access it from bash:
echo $TEST_ENV
test_me
I can't access this variable from GO
os.Getenv("TEST_ENV") // returns ""
If I list the available environment variables with
os.Environ()
I don't see the variable I'm looking for, but there a few variables that might help:
SHELL=/bin/sh
USER=root
LOGNAME=root
I guess my problem is related to different sessions and shells, so I even tried running
exec.Command("source /etc/profile")
and get the variables after, but it still returns nothing.
Can you give me some tips how to get environment variables if they're set in /etc/profile? I'd prefer getting them from that file, but if necessary, I can put the variables in a different place as well.
When you set an environment variable in bash, by default it isn't exported. Only exported environment variables are passed along to processes created by the shell (i.e., programs that you run). Try export TEST_ENV=test_me.

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.

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").

How to set environment variables in fish shell

Can someone please tell me what's the correct way to set a bunch of environment variables in the fish shell?
In my ~/.config/fish/config.fish file, I have a function to setup my environment variables like so:
function setTESTENV
set -x BROKER_IP '10.14.16.216'
set -x USERNAME 'foo'
set -x USERPASS 'bar'
end
When I type from the command prompt setTESTENV and do a env in the command line, I don't see this information.
Use Universal Variables.
If the variable has to be shared between all the current user Fish instances on the current computer and preserved across restarts of the shell you can set them using -U or --universal. For example:
set -Ux FOO bar
Using set with -g or --global doesn't set the variable persistently between shell instances.
Note:
Do not append to universal variables in config.fish file, because these variables will then get longer with each new shell instance. Instead, simply run set -Ux once at the command line.
Universal variables will be stored in the file ~/.config/fish/fish_variables as of Fish 3.0. In prior releases, it was ~/.config/fish/fishd.MACHINE_ID, where MACHINE_ID was typically the MAC address.
The variables you are declaring are keep in a local scope inside your function.
Use:
set -g -x
Here "g" is for global.
another option is to run:
export (cat env_file.txt |xargs -L 1)
where env_file.txt contains rows of the format VAR=VALUE
this has the benefit of keeping the variables in a format supported by other shells and tools
Environment Variables in Fish
I would like to add that, while #JosEduSol's answer is not incorrect and does help solve the OP problem, -g is only setting the scope to be global, while -x is causing the specified environment variable to be exported to child processes.
The reason the above fails, is because #cfpete is setting the env vars inside a function and the default scope will be local to that function.

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