Choosing between multiple executables with same name in Linux - linux

The system I am using has gnuplot installed in /usr/bin. I don't have root, but I needed a newer version of gnuplot, so I installed it to $HOME/usr/bin.
I added $HOME/usr/bin to my path, but it still executes the one in /usr/bin if I just use the gnuplot command. I'd rather not have to specify $HOME/usr/bin/gnuplot every time I have to use it.
How do I tell Linux to use the one in my home directory, and not the one in /usr/bin?

Executables are found in PATH order. You need to prepend ${HOME}/usr/bin to your path, like so:
export PATH="${HOME}/usr/bin:$PATH"

Executables are found in PATH order. Your PATH apparently is set up such that /usr/bin precedes ~/usr/bin/.

Besides modifying the PATH as has been explained, you can also use aliases like this (in BASH)
alias gn=$HOME/usr/bin/gnuplot
then you just run it with
gn

What Bombe says is ok. I would add that you should declare your user specific PATH entries inside your user's bashrc ($HOME/.bashrc), so your PATH settings only apply to your user.

Related

Copying shell file to path

I'm new to WSL and Linux, but I'm trying to follow installation instructions for rhasspy (https://rhasspy.readthedocs.io/en/latest/installation/#windows-subsystem-for-linux-wsl). I have run the make install command successfully and the next step says I should copy rhasspy somewhere in my path but I can't quite figure out what copying to path means.
When installation is finished, copy rhasspy.sh somewhere in your PATH and rename it to rhasspy.
I added it to path but nothing changed so I was wondering if there is something I'm doing wrong. Right now when I run rhasspy on wsl it says rhasspy.sh: command not found. Any help would be really appreciated!
What it says is, put it in some place where the system will look for it when you type its name without full path in the shell.
There is an environment variable PATH that contains all those locations, separated by a :. (Check out echo $PATH.)
So, the author of these instructions leaves it up to you whether...
You want to copy the file to a location of your choice that is already in the PATH, such as /usr/local/bin or ~/bin.
Usually ~/bin is a good choice because it is per-user and doesn't pollute the system.
(Note that the directory ~/bin is added to the PATH by your .profile file only if it exists, so if you don't have this directory yet and create it now, you need to start a new login shell or run . ~/.profile1 before you can use it.)
- OR -
You want to create a new directory specifically for this application (say for example ~/opt/rhasspy) and append that directory to the PATH variable.
This can be done by adding the line export PATH=$PATH:~/opt/rhasspy to your ~/.profile file. Then, start a new login shell or reload the file using . ~/.profile1 for the changes to take effect.
If the directory in which this file is currently located is OK for you to keep permanently, then you can also just add that directory to the PATH instead of creating a new one.
Note: The PATH always contains directory paths in which the shell will look for executable files. It does not contain the actual file paths!
1: Yes, technically it is "cleaner" to log into a new shell or to run that one export statement manually instead of using . ~/.profile because the latter will apply things a second time that were already done before, so for example it can end up with the same directory in the PATH multiple times in the current session. In most cases that is fine though.
PATH is an environment variable. When you launch env, you see the list of known environment variables on your system.
In order to add something to your PATH variable, you need to take the variable, add the mentioned directory (preceeded by a semi-colon, most probably, as a separator) and store this again as the PATH variable. This can be done as follows (own example):
export PATH=$PATH:/home/this_user
the "PATH" it is referring to in linux is just inside the folder called /usr/bin. when you type a command into the terminal it looks for a program with that name inside the location. im not sure if this is the PATH you are looking for but hope it helps

Python mechanism to load site-packages relative to program/script location?

For a set of programs written in most languages (C for instance) a script can normally run those programs without any sort of interference between dynamic link libraries and with no special hand holding so long as they are all found on PATH. That is, the following will work:
#!/bin/bash
prog1
prog2
prog3
However, if these three programs are written in Python and they import conflicting package versions then to run each one successfully it must either be installed into a virtualenv or each must have a separate site-packages directory which is referenced by PYTHONPATH. Either way they need a set up and possibly a tear down before running. That is, for virtualenv:
#!/bin/bash
source $PROG1_ROOT/bin/activate
prog1
deactivate
source $PROG2_ROOT/bin/activate
prog2
deactivate
source $PROG3_ROOT/bin/activate
prog3
deactivate
and for separate site-packages:
#!/bin/bash
export PYTHONPATH=$PROG1_ROOT/lib/python3.6/site-packages
prog1
export PYTHONPATH=$PROG2_ROOT/lib/python3.6/site-packages
prog2
export PYTHONPATH=$PROG3_ROOT/lib/python3.6/site-packages
prog3
This problem results because
import pkg_resources
(at least through Python3.6) cannot reliably import the proper versions when multiple versions of a package share the same site-package directory, even if __requires__ precedes it listing all the version restrictions.
It occurs to me that if PYTHONPATH, or some equivalent, could be specified relative to the program instead of the $PWD, and some consistency in directory layout was observed, then it would only have to be set once. That is, if prog1 is in $PROG1_ROOT/bin and its libraries are in $PROG1_ROOT/lib/python3.6/site-packages, then setting PYTHONPATH to "../lib/python3.6/site-packages" would work not only for prog1, but also for prog2, prog3, and for as many more as are needed through progN.
However, PYTHONPATH is normally provided as an absolute path, and relative paths are I believe with respect to $PWD, not to the python program (prog1). Is there some other Python path variable which has the desired property? Failing that, is there some type of file which could be dropped into $PROG1_ROOT/bin which would be normally picked up by a python program when it starts and which could direct it to use $PROG1_ROOT/lib/python3.6/site-packages? It would be OK to have either the relative or absolute path in that file, although the former would still be preferred because then one could move the entire PROG1_ROOT directory tree to another location in the file system without having to rewrite this special file. I really want to avoid solutions which would require modifying prog1 etc. themselves (ie, prog1 in the example).
Thanks.
EDITED:
I wrote this:
https://sourceforge.net/projects/python-devirtualizer/
to implement some of these ideas. At this point it is Linux (or at least POSIX) specific. It slightly modifies python scripts in a package's "bin" directory by changing the first line, and it "wraps" everything in that directory with a replacement native binary which injects a custom PYTHONPATH into the true target's environment. That binary looks up its location using a function from libSDL2 and then specifies the PYTHONPATH relative to that. So far it has worked pretty well, and the "programs" in installed python packages (the "bin" directory's contents) are run based on PATH just like any other program, no futzing about with PYTHONPATH in the shell.
Making search paths relative to the executable is a Very Bad Idea (TM). Move the executable or libraries around, all hell breaks loose. Some enterprising miscreant might notice the path settings and place a script just right to get their own doctored libraries (or just flawed old versions) to be used. And so on.
Clean up the misbehaving scripts. Chances are that by using old versions they are vulnerable to by now fixed security boo-boos, or other misbehaviours. Or find a way to load the stuff in the script itself.

multiple binaries with same name in ubuntu/linux

I have recently installed a webframework play (http://www.playframework.com/) and want to have the play executable in the system path ie $PATH. But ubuntu already defines a command called play. How do I overwrite the system defined command with my framework binary path so that command play on commandline calls my framework rather than the old application.
Installation: I downloaded zipped file of the framework and upzipped in one of my personal folder which contains the docs and the executable.
Never alter the contents of installed packages. Such changes can provoke hard to find problems in the system and anyway, they will most likely be overwritten again in subsequent updates. There are other alternatives:
obviously you can chose another name for your executable
place the executable in another part of your $PATH if its a "personal installation", typically ~/bin is used for such approach. Remember that the order of entries in the $PATH variable is important, first come first serve.
use the traditional /usr/local/bin location for locally added "wild" installations, this way there is some form of clean separation between clean packages and wild installed files inside the system
store your software in some other location and prepend that to your personal or system wide $PATH variable
store your executable under another name and create an alias (see man alias for an explanation) for it which allows to call it by some name that "hides" the original command this way. For this the executable can be addressed with an absolute path, so it dies not have to be found inside the $PATH variable.
In my personal opinion options 2. and 5. and the best if it comes to "personal installations".
If you are sure you'll never use the original play command, you could just remove the binary. But in general, this isn't a good idea, since some system component you don't think of might need it, and the next update will probably restore it.
The best thing to do is to prepend the directory of your play command to the PATH, for example, using PATH=/opt/framework/bin:$PATH in your .profile (assuming your play command installs to /opt/framework/bin/play), or the script that starts your web server, or wherever you need your play command.
Remember that does not make your play command global. A common mistake is to add the path in their .profile file, then call the program from crontab - crontab scripts will not execute .profile or .bashrc.

Advantage of $PATH over alias

I am relatively new to Linux and Unix. With the help of the internet I finally figured out how $PATH and aliases in my .bashrc work.
But I really couldn't find anything that describes when to use which.
Let's say I installed Python3.3 in Library/Frameworks and the executable is
/Library/Frameworks/Python.framework/Versions/3.3/bin/python3, but I want to execute python 3.3 just by typing python3 into my terminal.
When I understand it correctly, there are (at least) three methods to achieve this:
1) I modify $PATH in my .bashrc:
export PATH=/Library/Frameworks/Python.framework/Versions/3.3/bin:${PATH}
2) I set an alias in my .bashrc:
alias python3=/Library/Frameworks/Python.framework/Versions/3.3/bin
3) creating a symbolic link (symlink):
ln -s /Library/Frameworks/Python.framework/Versions/3.3/bin /usr/local/bin
What would you say (from your experience) is the "recommended" way?
Putting python3 in your path is the correct way to invoke it anywhere you might find yourself in your filesystem. A symbolic link is the best way to change that command to python and keep your scripts non version dependent (you can run a script that depends on python use the symbolic link and a script that needs python 3.0 specifically use python3, even though on your computer they are the same thing). Symbolic links are still files in your filesystem, so they still need to be in your path.
I only see aliases used when you are trying to create some kind of behavior that is different than the default behavior for a command line utility like an alias for ls that adds -a silently.
Also symbolic links are stored in the filesystem so once created they exist for all other users who log in, while aliases only apply to the logged in user who has defined them. They can also have file permissions applied to them.
Here is a fun article about things you can do to your terminal through your .bash_profile including some great aliases.
First, there is no reason to install Python in a /Library/Frameworks/ directory. My suggestion is that (at least for a beginner) you should not add top level directories like your /Library. If you compile it from source code, you should have built it with a standard ./configure (and it probably goes into /usr/local/)
I don't know well about compiling Python from source code, but most Linux source code gets by default ./configure-d to a /usr/local/ prefix so their binary go into /usr/local/bin/ which is often already by default in your PATH
Some Linux distributions have an /etc/profile which indirectly, if the directory $HOME/bin/ exists, adds it inside your PATH; in that case just adding binaries and scripts (or symbolic links) there is the most simple way.
My general advice is to avoid having a very long or very specific PATH. In particular, adding a directory inside your PATH for each product is IMHO a mistake. See e.g. the directory-variables section of GNU coding standards, and keep your PATH quite short. Personally I add programs only in /usr/local/bin/ (system-wide) or in $HOME/bin/, perhaps as symbolic links (so I don't change my PATH since it already contains both /usr/local/bin/ and $HOME/bin).
By past experience having a very long PATH is a nightmare, and slows down your interactive shells
Thank you all for your explanations.
As I already said, I am pretty new to Unix and Linux. I just wrote an article about those things (aliases, symlinks $PATH) for my blog for other "newbies". I like to write about those things, because they really interest me, and I want to share my experiences - I hope they are helpful to other people, too. Furthermore, it helps me to deepen my understanding if I have to explain things - and it is a good future reference, too!
It would be nice if you could skim over the article very quickly, and if I got some things wrong, I would be very happy about suggestions!
http://scientific-ocean.com/2013/02/17/an-introduction-to-linuxunix-executables-path-aliases-and-symlinks/
I would suggest go for alias which would make it easier for conflicts arising if you different versions of Python. The shell will look up the PATH variable and wherever it matches the executable of Python it will execute it. The alias has to be put in your shell profile like .bash_profile.

Where to put helper-scripts with GNU autoconf/automake?

I'm working on a project that will be distributed with GNU autoconf/automake, and I have a set of bash scripts which call awk scripts. I would like the bash scripts to end up in the $PATH, but not the awk scripts. How should I insert these into the project? Should they be put in with other binaries?
Also, is there a way to determine the final location of the file after installation? I presume that /usr/local/bin isn't always where the executables end up...
You can just list the scripts that you want to be installed in Makefile.am:
bin_SCRIPTS = foo bar
This will cause foo and bar to be installed during make install. To get the path to their final location, you can use #bindir# in foo.in and let configure build foo for you. For example, in configure.ac:
AC_CONFIG_FILES([foo bar])
and then in foo.in:
#!/bin/sh
prefix=#prefix#
exec_prefix=#exec_prefix#
bindir=#bindir#
echo bindir = $bindir
Keep in mind that the person running configure may specify any of --prefix, --exec_prefix, or
--bindir, and the installation may be redirected with a DESTDIR. Using the technique described here, DESTDIR will not be taken into account and the script will be installed in a location other than the path that it will echo. This is by design, and is the correct behavior, as usually a DESTDIR installation is used to create a tarball that will eventually be unpacked into the filesystem in such a way that the bindir in the script becomes valid.
Add something like this to Makefile.am
scriptsdir = $(prefix)/bin
scripts_DATA = awkscript1 awkscript2
In this case it will install awkscript in $(prefix)/bin (you can also use $(bindir)).
Note: Dont forget that the first should be named name + dir (scripts -> scriptsdir) and the second should be name + _DATA (scripts -> scripts_DATA).
Jonathan, in response to your additional question: if you want to replace the value of prefix at the time of build, you will need to:
rename your script 'myscript' to 'myscript.in'
add a rule to configure.ac to generate it at the bottom
use a macro I made called AS_AC_EXPAND
use it like this:
AS_AC_EXPAND(BINDIR, $bindir)
in your 'myscript.in', you can now use #BINDIR# and it will get expanded to the full path where the script will end up being installed.
Note that you shouldn't use PREFIX directly, any of the installation directories can potentially be changed so you really want to use the value passed to configure for bindir and expand that.
If the awk scripts won't go into the main bin directory (prefix/bin), then you need to place them in an appropriate sub-directory - probably of lib but possibly libexec or share (since the awk scripts are probably platform neutral).
Correct: software won't necessarily end up in /usr/local/bin; on my machine, /usr/local/bin is managed by MIS and all the software I install therefore goes under /usr/gnu/. I use: ./configure --prefix=/usr/gnu to get the software installed where I want it.
You can embed the value of PREFIX in the bash scripts -- effectively, you will 'compile' the scripts to include the install location. Be aware of problems during the build testing - you may need to locate the scripts relative to the current directory first and relative to PREFIX later.

Resources