I need to set the an environment variable from within Perl. Ideally, I need to query a variable and then change it if it is not what is required. Specifically it is the PATH variable I want to change.
How do I get and set these variables?
If you need to change environment variables globally and permanently, as if you set it in the control panel, then you have to muck with the registry (update: and now there are modules to do this, Win32::Env and Win32::Env::Path). Note that changing variables in the registry and "broadcasting" the change will not change the environment variables in some current processes, notably perl.exe and cmd.exe.
If you just want to change the current process (and subsequently spawned child processes), then the global %ENV hash variable is what you want (e.g. $ENV{PATH}). See perldoc perlvar.
$ENV{PATH}?
Keep in mind that environment variables only affect subprocesses, however. You can't run a Perl program, change %ENV, and then see that change in the parent process -- the environment does not work that way.
You can do that using the %ENV hash
$ENV{PATH} = 'C:\\Windows\;D:\\Programs';
Related
The help text for set -a is somewhat cryptic to me, but maybe i just don't understand what bash is doing behind the scenes with variables. Can someone explain why "marking" variables is needed (what are "unmarked" variables)?
My bash man-page uses a slightly different wording for this: Each variable or function that is created or modified is given the export attribute and marked for export to the environment of subsequent commands. This sounds more clear to me. It means:
Each variable you define in your script, is placed in the environment of any child process you create, and each function you define is also available to each bash-child-process you create.
What does % mean in windows environmental variables ?
%SystemRoot%\system32;
%SystemRoot%;
%SystemRoot%\System32\Wbem;
Especially the Path, TMP, TEMP variable values have this sign. There might be other variables also, but I came across only these three.
Do I need to bother about it while setting my own path variables ?
Do I need to bother about it while setting my own path variables ?
Under normal circumstances, no, you don't. You would only do this if you wanted the effective value of PATH to depend on some other environment variable. Even then it is only a convenience, never a necessity.
As a real-world example of when it might be convenient, suppose you've written a program that automates updating the Java SDK to the latest version, so your users don't have to do it by hand. Updating the SDK moves it to a different location, so you probably want to add the new location of the SDK to the path, and remove the old one.
You could do that the hard way, by parsing PATH each time, locating the part that points to the old location and changing it appropriately. But that's a pain, and if you're doing this globally, the users don't have any choice over whether Java is in the path, even if they don't use it. So instead you might create a variable JAVA_PATH that points to the current SDK location. That way, it is easy to change, and individual users can choose whether or not to put %JAVA_PATH% in their own paths.
In Microsoft's case (the examples you noticed) the system root is never going to move, but by using a variable they could hard-code the default value of PATH rather than having to explicitly generate it during operating system installation.
PS: the environment variables referenced in PATH must all be system variables. Referencing a user variable will not work.
%VariableName% is the syntax for referencing an environment variable. The actual name is the part between the % symbols.
So your first line, when fully expanded, would evaluate to the value of the SystemRoot variable, followed by \system32;.
You'll need to use %...% if you want to make use of environment variables in the Windows shell, or if you want to define environment variables that reference other variables.
I am writing a shell.
With the execvpe system call, I can run a program and control its environment. What are the minimum values I need to pass through here?
Alternatively, I understand that child processes should have a copy of their parent's environment, possibly with some values added. While testing my shell, I am running it from within bash from within my terminal from within a window manager, etc etc. What are the bare basics that I can assume are in my environment? If I were to run my shell straight from a TTY (the "lowest level", as far as I understand), what can I expect?
That’s a very broad question. To a certain extent,
programs should be able to run with no environment at all.
“X” display (i.e., GUI) programs need to know
where they are supposed to display.
This information is usually provided
through the DISPLAY environment variable,
but can also be passed on the command line.
There are probably other environment variables that are essential
(or nearly so) to “X” programs;
it’s been a while since I’ve looked under that hood.
Any program that needs to use special characteristics of your terminal
needs the TERM environment variable.
“Special characteristics” means being able to set colors
(as ls and grep can do, subject to options),
move around the screen (like vi / vim),
or even know the size of the screen (like less).
Note that size of the screen may also be available
through ROWS and COLUMNS.
Any program that needs to know the date and time
as perceived / understood by the user needs to know the time zone (TZ) —
although, if you’re willing to work with absolute (GMT / UTC),
you don’t need this.
etc.
The minimum that you need is a working PATH variable. Any extras beyond that depend on what programs you want to execute.
POSIX has a list of commonly-used environment variables, very few programs use more than a few of those.
Generally if you're using execvp*, you're not giving full pathnames for the executables. It makes your programs much simpler, you do not have to provide a full pathname for each executable, as is needed by the plain execv. POSIX describes these functions as
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
and (referring to the parameters of the various exec* functions):
The argument path points to a pathname that identifies the new process image file.
The argument file is used to construct a pathname that identifies the new process image file. If the file argument contains a slash character, the file argument shall be used as the pathname for this file. Otherwise, the path prefix for this file is obtained by a search of the directories passed as the environment variable PATH (see XBD Environment Variables). If this environment variable is not present, the results of the search are implementation-defined.
and (remember that "file" is referring to execvp rather than execv, so the environ variable applies to the search using PATH for the "file" parameter):
For those forms not containing an envp pointer (execl(), execv(), execlp(), and execvp()), the environment for the new process image shall be taken from the external variable environ in the calling process.
So... you could technically remove the entire PATH variable, but the result would be implementation-defined.
The minimum neccessary environment is empty. You don't need anything.
e.g.
$ env -i env
$
We can see that env -i has created a blank environment.
We can take this further:
$ env -i /bin/bash
sweh#server:/home/sweh$ env
LS_COLORS=
PWD=/home/sweh
SHLVL=1
_=/usr/bin/env
We can see that bash has set a few variables, but nothing was inherited.
Now such an environment may break some things; e.g. a missing TERM variable means that vi or less may not work properly
$ less foo
WARNING: terminal is not fully functional
foo (press RETURN)
So, really, you need to determine what programs you expect to run inside the environment and what their needs are.
Where I can get the full list of variables, replaced by the WinAPI function?
MSDN contains only a single example: %USERPROFILE%.
Is this list full and correct? http://www.rapidee.com/en/environment-variables
Call GetEnvironmentStrings to find out the environment for your process, at the point when you make the call. You will need to parse the double null-terminated string that is returned to find the name/value pairs.
Note that there is no single definitive list of environment variables. Each process maintains its own private environment. The environment is specified when the process is created. Typically it inherits from the environment of the parent process. But not always. It is perfectly possible, and normal, for the parent process to specify an environment for the child process that differs from its own.
Note also that the environment can change during the lifetime of the process. Calls made to SetEnvironmentVariable will modify the environment of the calling process.
You should be able to deduce by now that the list of variables in your link may or may not be found in an environment. An environment could contain all of those variables, or none of them. It could contain variables not found in that list. It could contain no variables at all.
Learn more about environment variables here: Environment Variables (MSDN).
What is the best approach for overriding variable when launching make command?
make PREFIX="/new_path"
PREFIX="/new_path" make
I suspect that it's not exactly the same since in the first case the overriding is specified as a parameter of the make command, while in the second case (if I guess well) we use the shell definition for setting the variable then call the command make.
As you say, it depends on what you mean by "best". Both are appropriate in different circumstances.
By default makefile variable assignments take precedence over environment variable settings, and command line arguments override makefile variable assignments.
So, if you want to be sure the setting you give is used, then you should always use the command line: make PREFIX="new/path". If you want to provide a default value for a makefile to use if it doesn't already have a value, you should use the environment.