Set environment variable with shelljs - node.js

I'm trying to set an env variable in node with shelljs
so here's the psudo code:
const shell = require('shelljs');
shell.exec('export MM=2');
shell.exec('echo $MM');
but this does not printout the value of MM
Any suggestions on how to set an env variable through node with export (execute bash command)?

Are you familiar with how environment variables work in general? The wikipedia article has a good high level summary here: https://en.wikipedia.org/wiki/Environment_variable
One of the more unique things about environment variables is how they behave across process boundaries. Each process has its own set of environment variables. You can modify the environment variables in your own process without any issues. Whenever you spawn (fork + exec) a child process, it inherits your set of environment variables. If you are the child process (the process that got execed), you can not set the environment variable of your parent process.
You might realize now that if process A creates a child process B, and B modifies the environment variables, A will not see the changes.
So shells handle this specially. export is a shell-built in. In other words, bash (or any other shell) will not actually execute an export command by invoking a binary. Instead the shell will understand what export needs to do and do that directly, adjusting the environment variables in the shell process, not in a separate child process. Then any further command that gets run will inherit the (updated) environment variables from the shell.
You need to do the same.
shelljs provides a separate object, env, for this purpose:
shell.env["MM"] = "2";

Related

Environment variables don't last after being set (in a container)

I don't know if being inside a docker container has any relation with the problem but for the record I am running all inside a container.
I tried running this script
import os
os.environ['A_VAR']='aValue'
thevalue=os.environ.get('A_VAR',None)
print(thevalue)
with this I set the environment A_VAR to some value and I can see it from the print that is set
then I run the following
import os
'
thevalue=os.environ.get('A_VAR',None)
print(thevalue)
and no, the value is not set.
Running ``printenv` also shows that the values is not set.
Why is setting the environment variable not working and how it should be done?
Environment variables are local the the process setting it and all processes spawned from it (they inherit the environment). So you can set the environment for the child processes, but not for the parent.
Your python script runs as its own process so any changes it made to the environment disappear when this process exits.

Windows Environment Variables - Troubling accessing updated environment variables in program

I have wrote an initialization script that sets user environment variables which are keys that have been hashed and encrypted...Once the keys have been created the key encryption exe is no longer required. I want to launch the main application and remove the init file containing the hashing and key encryption functions.
I am not having any trouble with any of the above...Everything works as should when independent of each other. The problem is that in order for the main application to have access to the newly created environment variables I need the init script to completely exit...
Everything I have tried, Popen with flags, os.system() and others have still left me in a situation where the parent process ends and the main application launches, however, the environment variables have not updated...I close and relaunch main.py and...boom the program sees the updated variables and all is fine.
All I want is the init script to run, spawn a new process that is not linked at all with init.py and then exit so it can be removed. I thought this would be simple but after many hours of head scratching and trying numerous things, I am still no closer.
If I have to I will simply bundle it as two separate .exe files but I wanted it to be a one click install type thing.
I am running windows 10 and this can be platform specific.
Links looked at:
How to stop/terminate a python script from running?
Using a Python subprocess call to invoke a Python script
Starting a separate process
https://docs.python.org/2/library/subprocess.html
Python: Howto launch a full process not a child process and retrieve the PID
And more...
Current closest result
p = Popen(["python","UserInterface.py"], stdin=PIPE, stdout=PIPE, stderr=PIPE,
creationflags=DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP)
Create an environment block, set the environment variable using SetEnvironmentVariable, and use CreateProcess to specify this environment block for the created process.
MSDN DOC:
To specify a different environment for a process, create a new
environment block and pass the pointer to it as a parameter to the
CreateProcess function.
...
To programmatically add or modify system environment variables, add
them to the
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session
Manager\Environment registry key, then broadcast a WM_SETTINGCHANGE
message with lParam set to the string "Environment". This allows
applications, such as the shell, to pick up your updates.

FISH: How to set a specific $fish_function_path while launching fish?

I'm trying to use the sshrc to execute fish with my own defined functions at the remote server.
I know there is a $fish_function_path variable that I can modify to prepend my custom path with my functions, but this variable seems global and I don't want to affect other fish users.
Is there any way to change this variable only for my single fish session or any other ways to use my fish functions only for a single session?
I have also tried setting and environment variable from the outer shell: fish_functions_path="$MY_FUNCTIONS_PATH" fish but it seems environment variables don't affect those inner variables of fish.
Used this docs.
Thanks!
Global variables, including $fish_function_path, are per-session. You might be thinking of universal variables, which are shared across sessions for a given user.
It should be fine to modify $fish_function_path for a given instance of fish - it won't affect any others.

Child shell does not get empty environment variables and arrays of parent shell

After installation of Ruby Version Manager (RVM) as root on an Ubuntu 14.04. I am confronted with a strange behaviour of bash. Let's have a look at the exported environment variables. I login as user ubunutu and run exportin my bash. Here are three of rvm's exported environment variables, others are available:
declare -ax chpwd_functions='([0]="__rvm_cd_functions_set" [1]="__rvm_after_cd")'
declare -x rvm_version="1.25.28 (stable)"
declare -x rvm_ruby_mode
Everything is pretty fine, but when I run bash -c export we get only:
declare -x rvm_version="1.25.28 (stable)"
Can someone explain me why all empty environment variables and all arrays are removed in the child bash? What must I do to ensure that really all environment variables of a parent shell are available within a child shell?
This problem is really a blocker for me. I am using vagrant and its shell provisioner. In one script I setup rvm and in a second one I must configure some gemsets. The problem is that in the second script the rvm commands do not run. The active shell only gets those environment variables of rvm with are non-arrays and non-empty. Manually sourcing of rvm.sh is no solution!
It is because as per last line of man bash:
Array variables may not (yet) be exported.
I read somewhere a note by BASH developer that it is because exporting an array is very complex and error prone.
Also this line:
declare -x rvm_ruby_mode
is only declaring a name of the variable with export attribute set (without value), if you assign it a value it will be available in the sub shell.
Here is post by BASH author on export of array in BASH.
A variable is created when a value is assigned to a name using the = operator, for example
foo=bar
creates a variable named foo with the value bar.
declare is used for two reasons: one, to allow dynamic creation of variables (which is beyond the scope of this question), and two, to set attributes on names (not necessarily variables). The command
declare -x rvm_ruby_mode
simply sets the export attribute of the name rvm_ruby_mode. To actually create a variable whose name has the export attribute set, you need to use the = operator, just as without the declare command.
declare -x rvm_ruby_mode=
Now rvm_ruby_mode is an empty variable whose named is marked for export.
I say "marked for export" because variables are not exported until a subshell is created. Until then, there is simply a list of names that, if the name has a value when a subshell/child process is created, are copied into the new environment. This list is separate from the list of actual variables (which again are names with associated values).
As to why arrays cannot be exported? The environment is technically not a set of variables, since a variable is a shell construct and the environment is something used by all processes in POSIX, whether or not run by a shell. The environment is simply a list of strings of the form <name>=<value>. There is no standard for how to pack the elements of an array into a single string which any process can parse and reconstruct into an appropriate data structure. While it's possible that bash could make an exception if it new the child process was another bash shell and come up with some way of embedding an array in the environment (like it does with function definitions), apparently this has not been done.

DejaGNU - want to use environment variable from Linux throughout tests

I have some existing DejaGNU tests I need to modify, I want to replace some hard coded /dev entries with an environment variable, e.g. instead of /dev/ttyS0 I want /dev/$PORT where PORT is defined in the parent Linux shell.
How do I get a variable from the parent shell into DejaGNU?
$env(PORT)
If you want to test whether the environment variable is set, you can use
[info exists env(PORT)]

Resources