Setting Environment Variables in Mathematica - wolfram-mathematica

I need to set an environment variable from a Mathematica notebook.
Environment["VARIABLE"]
gives the value of the variable. But is it possible to set a variable, too?

There's no built in function (to my knowledge), but you can just use
Run["set VAR=VALUE"]
or
!set VAR=VALUE
instead.
Edit: You'll want to see the documentation for the Run and RunThrough commands.

Environment variables set up with Run or RunThrough will not affect the Mathematica kernel itself but will only be visible to processes launched within the same Run or RunThrough command.
If the environment variable should be visible to the Mathematica kernel process, the gdb based hack described in the accepted answer to Is there a way to change another process's environment variables? can be used under Mac OS X:
SetEnvironment[var_String, value_String] := Module[{valueEscaped, cmd},
valueEscaped = StringTake[ToString[CForm[value]], {2, -2}];
cmd = "call (int) putenv (\"" <> var <> "=" <> valueEscaped <> "\")";
Put[OutputForm[cmd], "!gdb -n \"" <> First[$CommandLine] <> "\" " <> ToString[$ProcessID ]]
]
The Mathematica Put command is used to launch gdb and have it attach itself to the Mathematica kernel process. The gdb command call (int) putenv ("var=value") is then sent to gdb on stdin to set up the environment variable with putenv.
Caveat: Under Mac OS X gdb is only available if the Xcode developer tools are installed.

I am assuming you are going to do this before you try to run an external command right?
Why not instead just run "VARNAME=value; your_original_external_command"
that will temporarily set the evn variable.

Related

Shell script to create loop for command

So i have a tcl code that i need to run in ns2. As we all know i just have to type 'ns abc.tcl' in terminal. In my abc.tcl code i have a variable x which i need to change and run the code. Is there any way i can write a script that will change the value of x and run 'ns abc.tcl' in terminal, then change the value again and run 'ns abc.tcl' in terminal again for a set of values for x. I believe i need to write a shell script but i don't know anything about that. Can you tell me the format i should write the script in like what should i write first and where do i write my values of x and how to make it run 'ns abc.tcl in terminal: 'function()' 'do' 'done' etc... If you can direct me to specific links about that would be helpful.
The easiest way, providing it works, is to pass the value in as an argument.
Invoke your code as ns abc.tcl TheValueToPassIn.
Access the value within your code by indexing into the argv global variable with lindex, which should contain a list of all arguments after the script name:
set myValue [lindex $::argv 0]
However, it's possible that that won't work (depending on exactly what the ns program does). If so, pass the value in inside an environment variable:
Invoke your code as MYVAR=TheValueToPassIn ns abc.tcl.
Access the value within your code by looking in the global env array:
set myValue $::env(MYVAR)
There are many other ways to do it, but those two are very easy.

Setting Fish Environment Variable Only Once in Function

I am trying to use fish as my shell. When I login with LightDM, I want to start certain Xsession apps, but only when the shell in invoked at the outset by LightDM.
I have tried this in ~/.config/fish/config.fish:
###################################################################
# Start xsession applications, but only once.
if test -z "$XSESSION_STARTED"
set -xg XSESSION_STARTED 'f'
end
if test "$XSESSION_STARTED" = 'f'
xsession-apps
end
The function xsession-apps then starts all the apps in the background and sets the environment variable at the end like this:
set -xg XSESSION_STARTED "t"
But XSESSION_STARTED does not appear to get set to 't' and causes the xsession-apps function to get called every time, even when I start a new terminal within gnome-term.
What am I missing. Is there a better way to approach this?
even when I start a new terminal within gnome-term.
That is to be expected. Global variables are set within that particular fish. If you start another fish, it won't have it (unless you start it inside that fish, because the variable is exported).
There's a few ways to approach this:
Don't do it in config.fish at all - use the DE's autostart mechanism or at least ~/.xinitrc. This is the best and cleanest approach, and independent of your shell.
Use universal variables - these are stored persistently and shared for all fish sessions on the machine. The issue here is invalidating it - you need to unset the variable again once you logout/reboot, but if your machine crashed that wouldn't happen
Use a flag file on a tmpfs (i.e. in RAM) - this will be automatically invalidated if your machine stops, whatever the cause. You need to setup a tmpfs for it, though.
Here is the code I used in ~/.xsessionrc:
# Apps launched directly by X window managers don't have their environment set
if [ $SHELL = "/usr/bin/fish" ]
then
/usr/bin/fish -c xsession-apps
else
source ~/src/dotfiles/keychain.sh
source ~/src/dotfiles/shell/aliases
source ~/src/dotfiles/shell/env
source ~/src/dotfiles/xsession-apps
eval "$(~/.rbenv/bin/rbenv init -)"
fi
It initializes fish or bash/zsh, depending on what I'm in the mood for at the time. Lately, I'm liking fish. I then defined a fish function called xsession-apps to launch the things I wanted started up in my X session, such as dropbox, hplip, xmobar, etc. I have a similar setup as a bash script, also called xsession-apps that gets sourced if I'm not using fish.
By the way, I use xmonad as my windowing environment.

Is it possible to change environment variables within Batch and utilize them without restarting CMD prompt?

I want to setup a system wide environment variable within my batch script script running within the CMD prompt, I have been able to achieve this by calling:
setx MyEnvVar "C:\<Some Path>" /M
However when I do:
echo "MyEnvVar is %MyEnvVar%"
afterwards the statement that outputs at prompt is "MyEnvVar is" although the variable has been setup with setx and I can observe it through looking at the Windows - system properties - environment variables GUI.
I know this is because the CMD prompt has to be restarted for it to pick up the new environment variables however I don't want to stop the execution of my batch script and tell the user to manually restart the CMD prompt window and re-run my script so the environment variables are picked up. Is there some other way of getting around this?
It would be better if I could get around this without utilizing the "call" method and breaking the script to two segments
batchfileA - Code up until and including the call to change the environment variables thereafter utilize call method to call batchfileB
batchfileB- The rest of the original code placed inside batchfileB and called with call method within batchfileA
I had tried using set after the setx and echoed the result and the variable was null so I assumed that the value was not taking because I had to restart the CMD prompt what I forgot was I had enabled DelayedExpansion and had to use ! (exclamation marks) instead of % (percent) signs around my variable names

What environment variable is used to execute commands and .sh file in terminal

I successfully executed commands and .bat files in command prompt using XUL by this code:
Components.utils.import("resource://gre/modules/FileUtils.jsm");
var env = Components.classes["#mozilla.org/process/environment;1"]
.getService(Components.interfaces.nsIEnvironment);
var shell = new FileUtils.File(env.get("COMSPEC"));
var args = ["/c", "cd C:/ffmpeg/bin & record.bat"];
var process = Components.classes["#mozilla.org/process/util;1"]
.createInstance(Components.interfaces.nsIProcess);
process.init(shell);
process.runAsync(args, args.length);
But now I changed .bat files to .sh files to run for Ubuntu and need to run commands in terminal by using same code, so I need to change environment variable "COMSPEC" to something which works for terminal, I found that it is "TERM" but didn't work.
Is there any other environment variable or way to do this task?
The command to run shell files on Linux is fixed - it is always /bin/sh. So you would do:
var shell = new FileUtils.File("/bin/sh");
var args = ["-c", "record.sh"];
This isn't quite the correct approach - if you wanted to do it absolutely correctly you would look inside the script file and parse the first line (which is usually something like #!/bin/sh). And in the general case you wouldn't check the file extension but rather whether the file is executable (on Unix-like systems this is completely independent of the file extension). But I guess that you aren't very interested in the general case.

Use lua os.execute in windows to launch a program with out a flash of CMD

I am happily launching a program in a windows system from Lua using
strProgram = '"C:\\Program Files\\Ps Pad\\PSPad.exe"'
strCmd = 'start "" '..strProgram
os.execute(strCmd)
This works correctly, launching the program and the script finishing.
How ever it flashes up a command window for a fraction of a second, does any one have a way from Lua to launch a program.
Lua's os.execute command is based on the C standard library "shell" function. In Windows, this function will always create a command window, and it will always halt your current process until the window finishes. The latter also happens in Linux.
There is ultimately no way around this. Not through the Lua standard API. Because Lua needs to be light-weight and platform independent, the API is not allowed to use OS-dependent native APIs.
Your best bet would be to use the Lua Ex-Api module. It is effectively abandonware, and you may need to patch up a few compiler issues (I'm guessing the Windows port wasn't their first priority). But it is a reasonably good way to spawn processes. You can choose to wait until it finishes yourself, or let them run in parallel. And it won't throw up a command prompt window, unless the application itself uses one.
This is the piece of code I use to call a batch from Lua, maybe help.
In win console (command prompt) open and execute, same in unix (mac|nix)
-- sBatchFile = .bat for windows, .sh for x
function vfFork2(sBatchFile)
local b = package.cpath:match("%p[\\|/]?%p(%a+)")
if b == "dll" then
-- windows
os.execute('start cmd /k call "'..sBatchFile..'"')
elseif b == "dylib" then
-- macos
os.execute('chmod +x "'..sBatchFile..'"')
os.execute('open -a Terminal.app "'..sBatchFile..'"')
elseif b == "so" then
-- Linux
os.execute('chmod +x "'..sBatchFile..'"')
os.execute('xterm -hold -e "'..sBatchFile..'" & ')
end
end
This is a way to run a command without a console window using only the Lua standard API (i.e. no extra libraries). Tested on Win7 x64.
function exec_silent(command)
local p = assert(io.popen(command))
local result = p:read("*all")
p:close()
return result
end
Edit: see the comments below, it might not work for everyone. I'm not sure why.

Resources