Best way to get mpirun to have command inherit current environment? - mpi

When you do mpirun env it shows that the command doesn't inherit the current environment and I was wondering if there is a clean way (e.g. a CLI arg to MPI) to make this work?

Related

Can I use zsh as the default non-interactive shell for WSL2 Ubuntu?

I am trying to use Run/Debug Configurations on WebStorm, however it doesn't seem to source .zshrc and produces errors about not finding commands and environment variables. (An example of this would be yarn tauri dev when using Tauri)
I have installed Ubuntu 20.04 in WSL and the project I opened in WebStorm resides under the $HOME directory. WebStorm is installed in Windows.
For the interactive shell, I have made zsh the default by chsh -s $(which zsh), but when using Run/Debug Configurations it uses the default non-interactive shell, which is dash as far as I know. And my environment variables and PATH are all set in .zshrc, which is not sourced by dash.
It seems in CLion, it is possible to execute commands in the login shell according to this YouTrack issue, but such an option is not available on WebStorm.
Is it possible to use zsh instead of dash as the default non-interactive shell? If not, it would help me a lot to know what is the best practice in such situations.
There are several questions and points you make:
First, from the question title (and the summary at the end):
Can I use zsh as the default non-interactive shell for WSL2 Ubuntu?
Well, maybe (using symlinks), but it would be a really bad idea. So many built-in scripts rely on /bin/sh pointing to Dash, or at least Bash. While Zsh might be compatible with 99.9% of them, eventually there's a strong likelihood that some difference in Zsh would cause a system-level script to fail (or at least produce results inconsistent with those from Dash).
It is possible in Ubuntu to change the default non-interactive ("system" shell) from Dash to Bash with sudo dpkg-reconfigure dash. If you select "No" in the resulting dialog, then the system will be updated to point /bin/sh to bash instead of dash.
But not to Zsh, no.
when using Run/Debug Configurations it uses the default non-interactive shell, which is dash as far as I know
I don't run WebStorm myself, so I'm not sure on this exactly. Maybe #lena's answer (or another) will cover it for you, but if it doesn't, I'm noticing this doc page. It might be worth trying to specify Zsh in those settings, but again, I can't be sure.
And my environment variables and PATH are all set in .zshrc, which is not sourced by dash.
Hmm. I'm guessing you would need these set in a .profile/.zprofile equivalent regardless. I would assume that WebStorm is executing the shell as a non-interactive one, which means that it wouldn't even parse ~/.bashrc if Bash was your default shell.
... it would help me a lot to know what is the best practice in such situations.
Best practice is probably to make sure that your ~/.profile has any environment changes needed. Yes, this violates DRY (don't repeat yourself), but it's probably the best route.
Thanks to the answer here and the discussion below, I was able to figure it out. (Thank you, #NotTheDr01ds and #lena.)
The main problem is that WebStorm is installed on Windows and therefore knows only the environment variables in Windows. There are two ways to solve the problem as follows.
Sharing WSL's environment variable to Windows through WSLENV
Add the line below to .zshrc so that it sets $WSLENV when zsh starts.
export WSLENV=VAR_I_WANT_TO_SHARE:$WSLENV
# Don't forget to insert the colon
# And for some reason, appending the variable after $WSLENV didn't work well
In Windows, run
wsl -e zsh -lic powershell.exe
This runs WSL using zsh (logged-in and interactive), then runs powershell which brings you back to Windows. Although this doesn't seem to achieve anything, by going through zsh in WSL, .zshrc was sourced and therefore $WSLENV set as well. You can check if it worked well by running the below command after you've run the above.
$env:VAR_I_WANT_TO_SHARE
Run WebStorm from the PowerShell that was just created.
& 'C:\Program Files (x86)\JetBrains\WebStorm 2022.1.3\bin\webstorm64.exe'
When you run or debug any of the Run/Debug Configurations, you will see that the environment variable is shared successfully.
Setting the PATH in Windows
For most environment variables, the previous method works well. However, PATH is an exception. The Windows PATH is shared to WSL by default. The opposite doesn't work, probably because the PATH in WSL should not interfere with Windows.I've tried adding the $PATH of WSL into $WSLENV but it didn't seem to work.
In the end, what I did was manually adding each needed $PATH of WSL into the Windows PATH.
For example, if there was export PATH=$PATH:home/(username)/.cargo/bin in .zshrc, you can then add \\wsl$\Ubuntu\home\(username)\.cargo\bin to the Windows $env:Path using the Environment Variable window.
I might have made some mistakes, so feel free to leave an edit or comments.
You can try using npm config set script-shell command to set the shell for your scripts. Like npm config set script-shell "/usr/bin/zsh".
When npm run <script name> spawns a child process, the SHELL being used depends on NPM environment. Cм https://docs.npmjs.com/cli/run-script:
The actual shell your script is run within is platform dependent. By
default, on Unix-like systems it is the /bin/sh command, on Windows it
is the cmd.exe. The actual shell referred to by /bin/sh also depends
on the system. As of npm#5.1.0 you can customize the shell with the
script-shell configuration
See also https://github.com/npm/npm-lifecycle/blob/10c0c08fc25fea3c18c7c030d4618a401963355a/index.js#L293-L304

WSL PATH environment variable is incorrect / zsh config not loaded [duplicate]

I am using Ubuntu via WSL 2.0 on Windows 10 and would like to run Texlive from the Windows command line. To do so I prepended the Texlive folder to the path in /etc/environment (I also tried a number of other locations eg. $HOME/.bashrc):
C:\Users\scott\Documents>wsl echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/mnt/c/Windows/system32:...
C:\Users\scott\Documents>wsl
scott#SCOTT-PC:/mnt/c/Users/scott/Documents$ echo $PATH
/usr/local/texlive/2020/bin/x86_64-linux:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/mnt/c/Windows/system32:...
Why is there a difference between these two paths? Is it possible to change the first PATH variable?
To be honest, when I first looked at this question, I thought it would be an easy answer. Oh how wrong I was. There are a lot of nuances to how this works.
Let's start with the fairly "easy" part, though. The main difference between the first method and the second:
wsl by itself launches into a login (and interactive) shell
the shell launched with wsl echo $PATH is neither a login shell nor an interactive shell
So the first will source both login scripts (e.g. ~/.profile) and interactive startup scripts (e.g. ~/.bashrc). The second form does not get to source either of these.
You can see this a different way (and get to the solution) with the following commands:
wsl -e bash -c 'echo $PATH'
wsl -e bash -li -c 'echo $PATH'
The -li forces bash to run as a login and interactive shell, thus sourcing all of the applicable startup scripts. And, as #bovquier points out in the comments, a single quote is needed here to prevent PowerShell from interpolating the $ before it gets to Bash. That, or escape it.
You should be able to run TeX Live the same way, just replacing the "echo $PATH" with the startup command you need for TeX Live.
A second option would be to create a script that both adds the path and runs the command, and just launch that script through wsl /path/to/script.sh
That said, I honestly don't think that your current login/interactive PATH is coming from /etc/environment. In my testing, at least, /etc/environment has no use in WSL, and that's to be expected. /etc/environment is only sourced by PAM modules, and with no login check performed by WSL, there's no reason to invoke PAM in either the wsl nor the wsl echo $PATH commands.
I'd expect that you still have the PATH setting in ~/.bashrc or somewhere similar), and that's where the shell is picking it up from at the moment.
While this isn't necessarily critical to understanding the answer, you might also wonder, if /etc/environment isn't used for setting the default (non-login, non-interactive) path in WSL, what is? The answer seems to be that it is hard-coded into the init that starts up WSL. That init is also what appends the Windows path (assuming you don't have that feature disabled in /etc/wsl.conf).

How to run sbt multiple command in interactive mode

I want to run several sbt-commands within sbt interactive mode, i.e. without leaving the sbt "shell"?
(Note:
Some questions answer how to pass argument to sbt-commands using sbt in the standard shell. Not what I wnat here)
Example: I am in sbt interactive shell, and I want to run "test:compile", then "test"
I know test will call required compilation, but in this example I want to run the compilation of all sub-projects, before any test is started.
To run commands sequentially within the sbt shell, use ; to chain commands:
> ;test:compile ;test
Note however that running the test task will compile your sources if necessary without you having to explicitly running the compile task.

run a "source" bash shell script in qmake

I want to use the intel compiler for Qt, but using the intel compiler implies running the script
$ source /opt/intel/bin/compilervars.sh intel64
Of course, I could add this to ~/.bashrc, but this would not run it in QtCreator, where it still complains about missing icpc. So I want it to be a part of the main mkspec qmake file.
How can I execute that full bash command in qmake?
Short Answer: Using QMAKE_EXTRA_TARGETS and PRE_TARGET_DEPS, you can execute source /opt/intel/bin/compilersvars.sh intel64, but simply sourcing them will not solve your issue.
Long Answer: The QMake file is converted into a Makefile. Make then executes the Makefile. The problem you will run into is that Make executes each command in its own shell. Thus, simply sourcing the script will only affect one command, the command that executes the script.
There are a couple of possible ways to make things work:
Execute the script before starting Qt-Creator. I've actually done this for some projects where I needed to have special environment variables setup. To make my life easier, I created a shell command to setup the environment and then launch Qt-Creator.
Within Qt-Creator, modify the Build Environment for the project I've also used this trick. In your case, simply look at the environment setup by the script and change the "Build Environment" settings under the project tab for your project to match those setup by the script.
It might also be possible to modify QMake's compiler commands, but I am not sure you can make it execute two commands instead of one (source the script then execute the compiler). Further more, this will make the project very un-transportable to other systems.
You can create a shell script that does more or less the following:
#! /usr/bin/env sh
# Remove the script's path from the PATH variable to avoid recursive calls
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
export PATH=${PATH/$SCRIPT_DIR:/}
# Set the environment up
source /opt/intel/bin/compilervars.sh intel64
# Call make with the given arguments
make "$#"
Save it into a file named "make" in an empty directory somewhere, make it executable, then change the build environment in QT Creator to prepend PATH with the script's directory:
PATH=[dir-of-make-script]:${Env:PATH}
You can do this either in the project settings or once and for all in the kit settings.
Like this, QT Creator will be fooled into calling your make script which sets up your environment before calling the actual make binary. I use a similar technique under Windows with Linux cross-toolchains and it has been working well so far.

Command line app: Unix cd command

My Mac OS command line application is making Unix calls such as:
system("rm -rf /Users/stu/Developer/file);
perfectly successfully.
So why is the following not changing the current directory?
system("cd /Users/me/whatever");
system("pwd"); //cd has not changed
Because
system() executes a command specified in command by calling /bin/sh -c command, and returns after the command has been completed.
So each command is executed independently, each in a new instance of the shell.
So your first call spawns a new sh (with your current working directory), changes directories, and then exits. Then the second call spawns a new sh (again in your CWD).
See the man page for system().
The better solution is to not use system. It has some inherent flaws that can leave you open to security vulnerabilities. Instead of executing system() commands, you should use the equivalent POSIX C functions. Everything that you can do from the command-line, you can do with C functions (how do you think those utilities work?)
Instead of system("rm -rf ...") use this.
Instead of system("cd ...") use chdir().
Instead of system("pwd ...") use getcwd().
There are some differences, of course, but these are the fundamental equivalents of what you're trying to do.

Resources