How to concatenate paths in msys - msys2

In a bash shell script I have to set PYTHONPATH. We have the following code:
if [ ${OS} == Windows_NT ]; then
PYTHONPATH="${TEST_DIR}input;${TEST_DIR}"
else
PYTHONPATH="${TEST_DIR}input:${TEST_DIR}"
fi
export PYTHONPATH
This also works under msys2 as long as TEST_DIR is an absolute path. However, in my code TEST_DIR can be both an absolute and a relative path. When for example TEST_DIR=. msys2 does not perform a magic : to ; conversion, and as a result PYTHONPATH is not correctly set.
Underlying details
When msys2 exports a environment variable like
/c/first/path:/usr/local it transfroms that to external non-msys program to an Windows environment variable such as c:/first/path;c:/msys2/usr/local. In that process it converts the unix style file names to Windows style file names, and transforms the : to a ; -- which is needed as a : is a common part of a Windows file name. However, this seems not to happen when msys2 does not recognize the environment variable as a path, as seems the case with ./:./input.

A work around so far is to use code like:
case ${TEST_DIR} in
/*)
sep=":"
;;
*)
if [ ${OS} == Windows_NT ]; then
sep=";" # on windows when TEST_DIR is an relative path we shall concatenate paths in an environment variable with a ;
else
sep=":"
fi
esac
PYTHONPATH="${TEST_DIR}input${sep}${TEST_DIR}"
export PYTHONPATH
However, this looks clumsy and I am not convinced all possible paths are correctly handled.

As suggested by David Grayson the code as used under Linux also works under MSYS2 and there is no need to ever use a ; as a path separator. So the correct code to use both under Windows and linux is:
PYTHONPATH="${TEST_DIR}input:${TEST_DIR}"
export PYTHONPATH

Related

How to verify if in Singularity|Apptainer container?

According to the shell doc:
The change in prompt indicates that you have entered the container (though you should not rely on that to determine whether you are in container or not).
So other than the change in prompt, how should one determine whether they are in a container or not?
There are a few environment variables you can check for:
SINGULARITY_BIND - may still be empty if no binds/mounts are set
SINGULARITY_COMMAND - e.g., exec, shell, etc.
SINGULARITY_CONTAINER - path to the image on the host OS
SINGULARITY_ENVIRONMENT - usually /.singularity.d/env/91-environment.sh or something similar
SINGULARITY_NAME - filename of the singularity image
Alternatively, checking for the existence of /.singularity.d/Singularity. If inside a singularity container, that is a copy of the Singularity definition used when creating the image. In general, it is really unlikely for /.singularity.d to exist on a normal host OS unless someone did something really weird.
One way to do this is by passing the --cleanenv argument in the singularity shell command and checking if the PATH variable is the same as your host user's PATH:
#add an arbitrary file location to your PATH variable and check that it is present for the host
export PATH=$PATH:/path/to/foo/bar
echo $PATH
#now pull up a shell in your container with --cleanenv to ignore the environmental variables of the host - such as the PATH we just exported
singularity shell --cleanenv yourimage.sif
#check that /path/to/foo/bar is not in PATH in your container
echo $PATH

Perl - open with relative path Apache

We recently inherited a somewhat legacy perl application and we're working to migrate to a new server as well as setup a sandbox environment so we can start sorting the application out. The issue we're having is the code currently uses some relative paths for the open method. And currently works in their shared hosting environment (we have little access to)
open(HANDLE,"<../relative/path/to/file.txt")
We pulled all of the code, paths, etc. over and for the most part have the application up and running until we run into one of the scripts that does the above, opens a file with a relative path. Then it fails.
If we run the code via the command line, the relative paths work. If we modify the path to be the full path it works both via command line and through Apache (navigating to the page in the browser).
This makes me think there is some module or configuration option we need to set in Apache to allow for the perl scripts to access or use the open command with relative paths?
Relative paths are relative to the process's current work directory, which is not necessarily the same as a the directory containing the program. It fact, it's often / for daemons (and thus their children).
For paths relative to the program's location, use
use FindBin qw( $RealBin );
my $qfn = "$RealBin/relative/path/to/file.txt";
open(my $HANDLE, "<", $qfn)
As mentioned in the comment above. Our final solution was to use:
File::Basename qw( dirname );
chdir(dirname($0));
This allowed us to get the code working while also kept additional code modifications to a minimum.
I was running a script out of cgi-bin and wanted to open a template in htdocs/templates so I did this in my script...
# open the html template
my $filename = sprintf("%s/templates/test.tmplt", $ENV{DOCUMENT_ROOT});
my $template = HTML::Template->new(filename => $filename);
It is bad practice to specify file's path in open with a fixed string unless the path is predefined and never change - as for example with /etc/fstab in linux.
You should change the code to use variable(s) instead.
Define variable at the top of the script -- in feature if you need to change base and path you will know that you find it at the few first lines of the code.
In such situation add temporary in the code something as
use strict;
use warnings;
open( my $fh, '>', 'my_uniq_file.txt')
or die 'Couldn\'t open my_uniq_file.txt';
print $fh 'This directory is default base for path location';
close $fh;
Once you run your script from webserver you should look for the file my_uniq_tile.txt -- it's location will be default base of web server for the file(s) location.
Now adjust variables with file path accordingly.
use strict;
use warnings;
my $dir_project = './project_1/';
my $audio_data = 'audio_data.dat';
my $video_data = 'video_data.dat';
my $descr_data = 'descr_data.dat';
my $qfn = $dir_project . $audio_data;
open(my $fh, '<', $qfn)
or die "Couldn't open $qfn";
while( <$fh> ) {
chomp;
[do something with data]
}
close $fh;

How to set PATH variable in crontab via whenever gem

Is it possible to set the PATH or SHELL variable in a crontab via the whenever schedule.rb file?
# here I want to set the PATH and SHELL variable somehow
every 3.hours do
# some cronjob
end
I want this output in my crontab after my capistrano deploy:
SHELL=/bin/bash
PATH=/usr/local/bin:/usr/local/sbin:/sbin:/usr/sbin:/bin:/usr/bin:/usr/bin/X11
# some cronjobs
Ok, it seems as I found the solution. I found it here: https://gist.github.com/jjb/950975
I will update this answer when I have tested it
I have to put this into my schedule.rb
# If your ruby binary isn't in a standard place (for example if it's in /usr/local/bin,
# because you installed it yourself from source, or from a thid-party package like REE),
# this tells whenever (or really, the rails runner) where to find it.
env :PATH, '/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin'
You are already doing it when running zenity when setting DISPLAY, LANG etc.
If you want to set the shell, set it in the first line of /home/username/script/script1.sh using #!/bin/bash.
If you want to set the path, one way to do it is to set it before running the command:
5 9-20 * * * PATH=/usr/local/bin:/usr/local/sbin:/sbin:/usr/sbin:/bin:/usr/bin:/usr/bin/X11 /home/username/script/script1.sh > /dev/null
A alternate/better way is to create a simple wrapper script like so:
#!/bin/bash
export PATH=/usr/local/bin:/usr/local/sbin:/sbin:/usr/sbin:/bin:/usr/bin:/usr/bin/X11
# Absolute path to this script
SCRIPT=`readlink -f $0`
# Absolute directory this script is in
SCRIPTPATH=`dirname $SCRIPT`
#make sure we are in the same directory as the script1.sh - this is useful in case the script assumes it is running from the same directory it's in and makes relative directory/file references
cd $SCRIPTPATH
##run final script, and pass through all parameters that were passed to wrapper script.
/home/username/script/script1.sh "$#"

Setting LD_LIBRARY_PATH environment variable for loading a shared library at runtime (g++)

I'm having two problems related to the same issue:
I have a shared object saved in `pwd`/lib and while the executable that uses it compiles successfully (by using -l and -L switches), at runtime, it's giving me grief. If I try to run LD_LIBRARY_PATH=/my/absolute/path/to/library/directory ./test it works fine. But if I export LD_LIBRARY_PATH=/my/absolute/path/to/library/directory and do ./test it says that it can't find the shared library. However, if I do LD_LIBRARY_PATH=$LD_LIBRARY_PATH ./test again it works fine!! Any ideas on what I'm doing wrong?
Second issue is related to the exporting of the LD_LIBRARY_PATH env variable. If I open a terminal and type export LD_LIBRARY_PATH=/path/to/stuff and then type echo $LD_LIBRARY_PATH, the variable is correct. However if I write a script containing the export command, simply running it doesn't update the variable, instead I need to run source install.sh in order to actually persist the variable. What's the best solution for this?
Thank you for your time!
To answer the second question first:
source executes the script inside the current shell, ./install.sh opens and executes it in a different shell.
http://www.unix.com/unix-dummies-questions-answers/537-difference-between-source-exec-script.html
Now for your first question:
LD_LIBRARY_PATH=$LD_LIBRARY_PATH ./test sets the LD_LIBRARY_PATH variable before just one command (the ./test command). For the same reason above, I believe this isn't getting transferred to whatever shell ./test creates. To make it persist, you may need to put the export LD_LIBRARY_PATH=... in your ~/.bashrc
I have found sometimes adding -L explicitly via the CFLAGS environment variable is successful when LD_RUN_PATH was not. As in:
export CFLAGS=-L/opt/tool/lib

Do I simply delete the bashrc 'return' command?

I've been advised to remove the return command from my bashrc file in order to allow Ruby Version Manager to function properly. Do I simply delete the return command, or do I replace it with some other command? I am hesitant to mess with my System-wide shell without some proper direction. But I would really like to get RVM working as it is a time saver.
My bashrc is located in the etc directory and looks like this:
# System-wide .bashrc file for interactive bash(1) shells.
if [ -z "$PS1" ]; then
return
fi
PS1='\h:\W \u\$ '
# Make bash check its window size after a process completes
shopt -s checkwinsize
if [[ -s /Users/justinz/.rvm/scripts/rvm ]] ; then source /Users/justinz/.rvm/scripts/rvm ; fi
The last line, is an insert, described in the RVM installation.
I wouldn't. That return is probably there for a good reason. It obviously doesn't want to execute anything after that if the PS1 variable is empty.
I would just move the inserted line up above the if statement.
In addition, if that's actually in the system-wide bashrc file, you should be using something like:
${HOME}/.rvm/scripts/rvm
rather than:
/Users/justinz/.rvm/scripts/rvm
I'm sure Bob and Alice don't want to run your startup script.
If it's actually your bashrc file (in /Users/justinz), you can ignore that last snippet above.
The last line uses a file in a specific user's home directory, and as such should not be in the system-wide bashrc, since only root and that user will have access to that file. Best to place it in that user's ~/.bashrc instead.