How to switch NVM environments within perl - perl

I am writing a perl script, and I want to run a simple shell command to use a certain version of NVM:
Here is my code snippet:
print "\n*** Switching to correct nvm environment for dashboard builds\n";
system("nvm use 8.12.0") == 0 or die $?;
But I am getting the following error:
Can't exec "nvm": No such file or directory
Can someone help?
Update (June 30, 2021):
I also tried adding the command:
my $nvm_version = "8.12.0";
system ("bash", "-lic", "nvm use $nvm_version");
But nothing happens:

I'm not familiar with nwm, but I think I get the gist of what it does. And if so, the attempt is fundamentally flawed. Even if you fixed this to run the proper shell so that nvm could run, I believe all the tool does is change the shell's environment variables, a shell you immediately exit. This means it would have no effect even if if it ran successfully.
Again, it this tool does what I think it does, such tool are meant to be used in interactive shells. In other instances, you simply use the path the to correct executable instead of relying on the PATH.
With that in mind, you can use the following to run the command in bash:
# Non-interactive shell.
system("bash", "-c", "nvm use 8.12.0")
or
# Interactive shell.
# This is improper and fragile as interactive shells
# often create aliases that override basic commands.
system("bash", "-ic", "nvm use 8.12.0")
Just to reiterate, at least one of these will allow the command to run (if it normally works from bash), but I believe it's unlikely this will produce the results you expect.

The nvm command is shell function which is different from a shell command. Also the nvm command is not an exported function so it will not be seen by sub shells. For example, in Bash shell:
$ nvm ls
-> v15.0.1
$ my-test-script.sh
./my-test-script.sh: line 3: nvm: command not found
where my-test-script.sh is:
#! /bin/bash
nvm use 16.4
The error nvm: command not found is because nvm is not exported. I can source the script in the current shell context to make it work:
$ source my-test-script.sh
Now using node v16.4.0 (npm v7.18.1)
$ node --version
v16.4.0
So a Perl script cannot change the node version of the current shell, but it can calculate the version and pass it back to shell, which can set the version. For example:
$ nvm use $(perl -E'$v=15.0; print $v')
Now using node v15.0.1 (npm v7.0.3)

Related

eval is not recognised on Windows

I am beginner and I'm trying to connect my GitHub profile with my local machine.
I'm following the steps but my git cmd does not recognise eval.
I have generated a key and am trying to add an SSH key to the ssh-agent.
This is the message I get:
'eval' is not recognized as an internal or external command,
operable program or batch file.
The command I run is:
eval "$(ssh-agent -s)"
You are running the command in the wrong console.
Open Powershell, Git Bash console or WSL bash - depending on how you installed Git - because this is just Command Prompt (cmd.exe) which doesn't support even the syntax you're trying (Bash).
Or alternatively, ensure ssh-agent's folder is in the PATH environment variable. Then you'll be able to call it even from a different console, that is, a part of the eval $(ssh-agent -s) command.
What that part does is nevertheless incompatible with the Command Prompt console:
-s Generate Bourne shell commands on stdout. This is the default if
SHELL does not look like it's a csh style of shell.
and outputs something like this:
SSH_AUTH_SOCK=/tmp/ssh-jR0WcW41z0yX/agent.1918430; export SSH_AUTH_SOCK;
SSH_AGENT_PID=1918431; export SSH_AGENT_PID;
echo Agent pid 1918431;
which might be worked around by using Command Prompt's SET command like this:
set SSH_AUTH_SOCK=c:\some\path\agent.1918430
set SSH_AGENT_PID=<the number you got>
and then run the commands following that eval $(ssh-agent -s) instruction.

In Jupyter Notebooks on Google Colab, what's the difference between using % and ! to run a shell command?

Question is in the title.
I know that % usually denotes a "magic variable" in IPython. That's not a concept I'm terribly familiar with yet, but I have read about it.
However, today I saw a tutorial where someone was using it to run a shell command. Normally I have seen and used !.
Is there a difference? Both seem to be doing the same thing when I try them.
The difference is this:
When you run a command with !, it directly executes a bash command in a subshell.
When you run a command with %, it executes one of the magic commands defined in IPython.
Some of the magic commands defined by IPython deliberately mirror bash commands, but they differ in the implementation details.
For example, running the !cd bash command does not persistently change your directory, because it runs in a temporary subshell. However, running the %cd magic command will persistently change your directory:
!pwd
# /content
!cd sample_data/
!pwd
# /content
%cd sample_data/
!pwd
# /content/sample_data
Read more in IPython: Built-in Magic Commands.

How to set environment variables in fish shell script

In my fish shell script 'hoge.fish`, I have a code to set envs.
#!/usr/local/bin/fish
set -x HOGE "hello"
but after I exec this script the env is not set correctly and outputs nothing.
./hoge.fish
echo $HOGE
I've tried these code but none of these worked.
set -gx HOGE "hello"
set -gU HOGE "hello"
how can I fix this?
OS: macOS High Sierra 10.13.6
fish version: 2.7.1
iTerm2: 3.2.0
When you ran the script, it probably set the environment variable correctly, but only in the process that was created when you ran the script....not in the parent session you ran the script from! When the script exited, the process and its environment were destroyed.
If you want to change the environment variable in your current environment, depending on what interactive shell you're using, you can use a command like source hoge.fish, which will execute the commands in your current session rather than a subprocess, so the environment variable changes will persist.
While sourceing, as in the original answer is definitely the correct mechanism, a comment from the OP to that answer mentioned that they would still prefer a solution that could be executed as a script.
As long as the variables are exported (set -x) in the script, it's possible (but still not necessarily recommended) to do this by execing into another fish shell inside the script:
#!/usr/bin/env fish
set -gx HOGE hello
exec fish
Executing ./hoge.fish will then have a fish shell with HOGE set as expected.
However, be aware:
This will result in two fish shell processes running, one inside the other. The first (parent) is the original fish shell. It will spawn a second (child) process based on the shebang line, which will then be replaced by the third instance from the exec line.
You can reduce the number of shells that are running simultaneously by starting the script with exec ./hoge.fish. That results in the shebang script replacing the parent process, and then being replaced by the exec line at the end of the script. However, you will still have run fish's startup twice to achieve what a simple source would have done with zero additional startups.
It's also important to realize the environment of the new shell will not necessarily be the same as that of the original shell. In particular, local variables from the original shell will not be present in the exec'd shell.
There are use-cases where these pitfalls are worth execing a new shell, but most of the time a simple source will be preferred.
Consider that if you run that from bash shell it will not export the variables with the -U option because it indicates to export to "fish universe" not outside.
If you stay inside fish's shell you still can do it like this:
#!/usr/local/bin/fish
set -Ux HOGE "hello"
And this is the result:
Welcome to fish, the friendly interactive shell
Type help for instructions on how to use fish
~/trash $ ./hoge.fish
~/tr ash $ echo $HOGE
hello
Remember to keep the first line so fish will interpret it properly.

Change shell within Perl script

I am looking for a nice way to get the following done:
So I have a script that I need to run in Python in Unix by calling from a Perl script that was, in turn, called from my Excel VBA macro in Windows using Plink. The Python script, due to dependency issues, has to run in either csh or bash, and I will need to use export/setenv to add a few libraries before running the script. However by default, perl runs in sh shell and as such, there is no way I can add in all the dependencies and have the Python script to run.
So, I am just wondering if there is EITHER: 1. a way for me to add dependencies to sh shell in the perl script, OR 2. force my perl script to run in csh (preferred, since for some reason .bashrc for the account runs into permission issues).
Thanks a lot!
How about "3. Set the appropriate environment variable in the Perl or Python scripts"?
$ENV{'PATH'} = ...
...
os.environ['PATH'] = os.pathsep.join(newpaths + os.environ['PATH'].split(os.pathsep))
(dunno how to get the path separator in Perl, sorz)
To force the shell to csh, try the following in Perl :
`/bin/csh -c "command_name"`;
Edit:
You can use ENV variable, like this. Try that :
$s = `/bin/bash -c 'VAR_FOO=753; echo \$VAR_FOO'`;
print $s;
I ended up just change the .cshrc script, apparently the addition to PATH, for some reason, did not work for me. After that, everything runs smoothly by putting all into one line
so basically it looks something like this
/path/to/.cshrc && /python/path/to/python
Hope that helps!

running ipython in non-interactive mode

I was hoping it would be easy to rewrite a few bash scripts using ipython by using the "!" command. Unfortunately if I try to run ipython in non-interactive mode like so:
ipython -p sh myipythonscript.py
where myipythonscript.py contains commands like:
env=%env
d=!ls
This doesn't work. I get SyntaxError.
Is there an option which allows ipython to be run in non-interactive mode?
Python also has modules which makes it easy to completely replace bash calls. these are easier to debug and give better error handling.
for example instead of ls you can use glob, it supports the same syntax:
files=glob.glob('myfiles*.txt')
for environment variables:
env = os.environ
for path related functions:
os.path
for common operations, os.mkdir, os.chmod, os.getcwd [same as pwd]