This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What should Linux/Unix 'make install' consist of?
I'm making a program that can be invoked from the command line, like ./prog arg1 arg2. I was wondering, how can I make it so that I can run it from anywhere on the system? I know that I could put prog into /usr/bin/, but what if my program needs resources from its install directory (that can be wherever the user downloaded it)?
put the directory in which your program resides into the path environment variable or move your program into one of the directories already in path (usually requires superuser permission, which I gather you don't have for then you wouldn't ask this question).
to add a directory to the front of the search path and have the system refresh its database on tcsh, say
setenv "my/directory:"$PATH
rehash
on bash, I think, it's
PATH=/my/directory:$PATH
export PATH
(no need to rehash). Note that the above commands put your directory at the top of the search path, i.e. these will be searched before any other. Thus, if your program is called "gcc", then your program will be executed rather than the GNU C compiler. Alternatively, you can add your directory to the end of the search path, in which case your program will only be picked up if no other program of the same name is found in any of the other directories in the search path.
You probably also want to become familiar with the Linux Filesystem Hierarchy: the standard definition for "what goes where". Here's more information:
https://superuser.com/questions/90479/what-is-the-conventional-install-location-for-applications-in-linux
Environment variables can be defined globally ("for everybody", e.g. /etc/profile), or locally ("per user", e.g. ~/.bashrc). Here's a good summary of some of your options:
https://wiki.archlinux.org/index.php/Environment_Variables
When you execute a programme using prog arg1 arg2, it's thanks to your shell, which search in the $PATH environement variable for folders where programs are. (Try env | grep PATH to see those folder).
You need eather to add a new directory in this variable (export PATH="/new/directory/path/:$PATH" if under bash, setenv PATH "/new/directory/path/:$PATH" if with tcsh) or copy your program and all the files it need to execute in one of the PATH folder.
There are two ways of dealing with this (and Makefiles have nothing to do with them)
Your installer could just put the files where it wants them, so your program doesn't have to search -- it can use hardcoded paths. Or you could put the path to the data directory into yet another file, which would be hardcoded (like /etc/programname.config).
You put all your stuff into one directory (often something like /opt/programname). You can hardcode that too, of course, or your program can readlink() the /proc/pid/exe file for a good chance (no guarantee, though. In particular, it works if for example a symlink is used to point from /usr/bin/programname to your /opt/programname/bin/programname or whatever, but it won't work if that's a hardlink)
to get the path to the executable. From there you should be able to reach your data files.
If prefer the second solution, but that's just me. The first solution works well with package managers, and it's less overkill if you don't really have a lot of data files.
Related
When running scripts in bash, I have to write ./ in the beginning:
$ ./manage.py syncdb
If I don't, I get an error message:
$ manage.py syncdb
-bash: manage.py: command not found
What is the reason for this? I thought . is an alias for current folder, and therefore these two calls should be equivalent.
I also don't understand why I don't need ./ when running applications, such as:
user:/home/user$ cd /usr/bin
user:/usr/bin$ git
(which runs without ./)
Because on Unix, usually, the current directory is not in $PATH.
When you type a command the shell looks up a list of directories, as specified by the PATH variable. The current directory is not in that list.
The reason for not having the current directory on that list is security.
Let's say you're root and go into another user's directory and type sl instead of ls. If the current directory is in PATH, the shell will try to execute the sl program in that directory (since there is no other sl program). That sl program might be malicious.
It works with ./ because POSIX specifies that a command name that contain a / will be used as a filename directly, suppressing a search in $PATH. You could have used full path for the exact same effect, but ./ is shorter and easier to write.
EDIT
That sl part was just an example. The directories in PATH are searched sequentially and when a match is made that program is executed. So, depending on how PATH looks, typing a normal command may or may not be enough to run the program in the current directory.
When bash interprets the command line, it looks for commands in locations described in the environment variable $PATH. To see it type:
echo $PATH
You will have some paths separated by colons. As you will see the current path . is usually not in $PATH. So Bash cannot find your command if it is in the current directory. You can change it by having:
PATH=$PATH:.
This line adds the current directory in $PATH so you can do:
manage.py syncdb
It is not recommended as it has security issue, plus you can have weird behaviours, as . varies upon the directory you are in :)
Avoid:
PATH=.:$PATH
As you can “mask” some standard command and open the door to security breach :)
Just my two cents.
Your script, when in your home directory will not be found when the shell looks at the $PATH environment variable to find your script.
The ./ says 'look in the current directory for my script rather than looking at all the directories specified in $PATH'.
When you include the '.' you are essentially giving the "full path" to the executable bash script, so your shell does not need to check your PATH variable. Without the '.' your shell will look in your PATH variable (which you can see by running echo $PATH to see if the command you typed lives in any of the folders on your PATH. If it doesn't (as is the case with manage.py) it says it can't find the file. It is considered bad practice to include the current directory on your PATH, which is explained reasonably well here: http://www.faqs.org/faqs/unix-faq/faq/part2/section-13.html
On *nix, unlike Windows, the current directory is usually not in your $PATH variable. So the current directory is not searched when executing commands. You don't need ./ for running applications because these applications are in your $PATH; most likely they are in /bin or /usr/bin.
This question already has some awesome answers, but I wanted to add that, if your executable is on the PATH, and you get very different outputs when you run
./executable
to the ones you get if you run
executable
(let's say you run into error messages with the one and not the other), then the problem could be that you have two different versions of the executable on your machine: one on the path, and the other not.
Check this by running
which executable
and
whereis executable
It fixed my issues...I had three versions of the executable, only one of which was compiled correctly for the environment.
Rationale for the / POSIX PATH rule
The rule was mentioned at: Why do you need ./ (dot-slash) before executable or script name to run it in bash? but I would like to explain why I think that is a good design in more detail.
First, an explicit full version of the rule is:
if the path contains / (e.g. ./someprog, /bin/someprog, ./bin/someprog): CWD is used and PATH isn't
if the path does not contain / (e.g. someprog): PATH is used and CWD isn't
Now, suppose that running:
someprog
would search:
relative to CWD first
relative to PATH after
Then, if you wanted to run /bin/someprog from your distro, and you did:
someprog
it would sometimes work, but others it would fail, because you might be in a directory that contains another unrelated someprog program.
Therefore, you would soon learn that this is not reliable, and you would end up always using absolute paths when you want to use PATH, therefore defeating the purpose of PATH.
This is also why having relative paths in your PATH is a really bad idea. I'm looking at you, node_modules/bin.
Conversely, suppose that running:
./someprog
Would search:
relative to PATH first
relative to CWD after
Then, if you just downloaded a script someprog from a git repository and wanted to run it from CWD, you would never be sure that this is the actual program that would run, because maybe your distro has a:
/bin/someprog
which is in you PATH from some package you installed after drinking too much after Christmas last year.
Therefore, once again, you would be forced to always run local scripts relative to CWD with full paths to know what you are running:
"$(pwd)/someprog"
which would be extremely annoying as well.
Another rule that you might be tempted to come up with would be:
relative paths use only PATH, absolute paths only CWD
but once again this forces users to always use absolute paths for non-PATH scripts with "$(pwd)/someprog".
The / path search rule offers a simple to remember solution to the about problem:
slash: don't use PATH
no slash: only use PATH
which makes it super easy to always know what you are running, by relying on the fact that files in the current directory can be expressed either as ./somefile or somefile, and so it gives special meaning to one of them.
Sometimes, is slightly annoying that you cannot search for some/prog relative to PATH, but I don't see a saner solution to this.
When the script is not in the Path its required to do so. For more info read http://www.tldp.org/LDP/Bash-Beginners-Guide/html/sect_02_01.html
All has great answer on the question, and yes this is only applicable when running it on the current directory not unless you include the absolute path. See my samples below.
Also, the (dot-slash) made sense to me when I've the command on the child folder tmp2 (/tmp/tmp2) and it uses (double dot-slash).
SAMPLE:
[fifiip-172-31-17-12 tmp]$ ./StackO.sh
Hello Stack Overflow
[fifi#ip-172-31-17-12 tmp]$ /tmp/StackO.sh
Hello Stack Overflow
[fifi#ip-172-31-17-12 tmp]$ mkdir tmp2
[fifi#ip-172-31-17-12 tmp]$ cd tmp2/
[fifi#ip-172-31-17-12 tmp2]$ ../StackO.sh
Hello Stack Overflow
I have a script library stored in .../lib/ that I want to embed into my program. So far, that sounds simple: On Windows, I'd use Windows Resource Files - on MacOS, I'd put them into a Resource folder and use the proper API to access the current bundle and it's resources. On plain Linux, I am not too sure how to do it... But, I want to be cross-platform anyway.
Now, I know that there are tools like IncBin (https://github.com/graphitemaster/incbin) and alike, but they are best used for single files. What I have, however, might even require some kind of file system abstraction.
So here is the few guesses and estimates I did. I'd like to know if there is possibly a better solution - or others, in general.
Create a Zip file and use MiniZ in order to read it's contents off a char array. Basically, running the zip file through IncBin and passing it as a buffer to MiniZ to let me work on that.
Use an abstracted FS layer like PhysicsFS or TTVFS and add the possibility to work off a Zip file or any other kind of archive.
Are there other solutions? Thanks!
I had this same issue, and I solved it by locating the library relative to argv[0]. But that only works if you invoke the program by its absolute path -- i.e., not via $PATH in the shell. So I invoke my program by a one-line script in ~/bin, or any other directory that's in your search path:
exec /wherever/bin/program "$#"
When the program is run, argv[0] is set to "/wherever/bin/program", and it knows to look in "/wherever/lib" for the related scripts.
Of course if you're installing directly into standard locations, you can rely on the standard directory structure, such as /usr/local/bin/program for the executable and /etc/program for related scripts & config files. The technique above is just when you want to be able to install a whole bundle in an arbitrary place.
EDIT: If you don't want the one-line shell script, you can also say:
alias program=/wherever/bin/program
I'm developing a C++ program under Linux. I want to put some stuff (to be specific, LLVM bitcode files, but that's not important) in libraries, so I want the following directory structure:
/somewhere/bin/myBin
/somewhere/lib/myLib.bc
How do I find the lib directory? I tried to compute a relative part from argv[0], but if /somewhere is in my PATH, argv[0] will just contain myBin. Is there some way to get this path? Or do I have to set it at compile time?
How do GNU autotools deal with this? What happens exactly if I supply the --prefix option to ./configure?
Edit: The word library is a bit misleading in my case. My library consist of LLVM bitcode, so it's not an actual (shared) object file, just a file I want to open from my program. You can think of it as an image or text file.
maybe what you want is :
/usr/lib
unix directory reference: http://www.comptechdoc.org/os/linux/usersguide/linux_ugfilestruct.html
Assume your lib directory is "../lib" relative to executable
First you need to identify where myBin located, You can get it by reading /proc/self/exe
Then concat your binary file path with "../lib" will give you the lib directory.
You will have to use a compiler flag to tell the program. For example, if you have a plugin dir:
# Makefile.am
AM_CPPFLAGS = -DPLUGIN_DIR=\"${pkglibdir}\"
bin_PROGRAMS = awesome_prog
pkglib_LTLIBRARIES = someplugin.la
The list of directories to be searched is stored in the file /etc/ld.so.conf.
In Linux, the environment variable LD_LIBRARY_PATH is a colon-separated set of directories where libraries should be searched for first, before the standard set of directories; this is useful when debugging a new library or using a nonstandard library for special purposes.
LD_LIBRARY_PATH is handy for development and testing:
$ export LD_LIBRARY_PATH=/path/to/mylib.so
$ ./myprogram
[read more]
Addressing only the portion of the question "how to GNU autotools deal with this?"...
When you assign a --prefix to configure, basically two things happen: 1) it instructs the build system that everything is to be installed in ${prefix}, and 2) it looks in ${prefix}/share/config.site for any additional information about how the system is set up (it is common for that file not to exist.) It does absolutely nothing to help find libraries, but depends on the user having set up the tool chain properly. If you want to use a library in /foo/lib, you must have your toolchain set up to look there (eg, by putting /foo/lib in /etc/ld.so.conf, or by putting -L/foo/lib in LDFLAGS and "/foo/lib" in LD_LIBRARY_PATH)
The configure script relies on you to have the environment set up. It does not help you set up that environment, but does help by alerting you that you have not done so.
You could use the readlink system call on /proc/self/exe to get the path of your executable. You might then use realpath etc.
Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 12 years ago.
Improve this question
If you look at point (6) here: http://www2.warwick.ac.uk/fac/sci/moac/students/peter_cock/cygwin/part3/
Why should we type ./ before the .exe file in order for it to run?
Why cannot we type hello.exe immediately?
Thanks.
Usually because intelligent people don't have their current directory . on the path :-)
The path is an environment variable like /bin:/usr/bin:/usr/sbin, and it's a list of directories to look in for finding executables, such as when you type in hello.
Unlike Windows, many UNIX shells don't automatically search the current directory for an executable. They must be listed in the path otherwise they are not run.
That's because to do otherwise is actually an attack vector. For example, if you create an ls program in your home directory and tell one of the administrators that there's a funny file in there, they may go to your directory and enter ls to see what's in there.
For a silly administrator that has the current directory before the "real" location of ls, they are now compromised, because your code is running with their full privileges.
That's why they tend not to do that.
Some people (not I) will put . on their path to make their lives easier but, even then, they'll put it at the end so that other locations are searched first.
Administrators don't have the luxury of being that trusting.
Because the current working directory is not in the PATH?
Or at least, that's how things are setup on Unix-style systems, I assume CYGWIN does the same.
On Windows, the current directory is always in the search path for an executable. The search order is "look in the current dir, if not found, look in the directories listed in the PATH environment variable".
From MS site:
The operating system always searches
in the current directory first, before
it searches the directories in the
command path.
(which makes all the warning here of not putting the . in your PATH irrelevant, IMHO)
On Linux this is not the case (for current dir). So, to run an executable which is in your current dir you need to write ./exe_name.
As Cygwin, again AFAIK, is for Windows, the ./ is not needed and seems to be just a copy/paste or preserving the unix-style the writer is used to.
EDIT: this is the issue of the command processor (the shell) as pointed out in comments and as I explain below, so if you are using a Unix-like shell on Windows, you still may need this style.
EDIT: elaborating on .\
. (not ./ to be exact) is an alias to the current directory. On Unix, every newly created directory is not "born" empty but contains 2 children: ., which is a self-reference, and .. which is a reference to the parent directory. Both are just regular directories, as any other. You don't see them when you run the ls command (same as dir on Windows) because names starting with . are special in the sense that they are not displayed by default. However, you can see them by ls -a.
When you run a command at the prompt, if the command is only a (file) name, the system (actually, the shell) searches the PATH for the file with this name.
If the command contains a path (not necessarily an absolute path, e.g. subdir1/exe) the system looks for the executable where you specified. Hence, writing ./exe means file exe in the current dir.
Cygwin is a Unix-like runtime environment and as such follows the way paths are searched for executables in such environments. The default executable search path of Unices does not contain the current directory. Thus if one wants to run an executable not located in one of the directories set in PATH a full path must be given. ./ is a shorthand for the current directory, also called process working directory (pwd). Be advised that it's a very bad idea to have the pwd being included in the executable search path.
Cygwin follows the Unix limitations on executing files in the current working directory. In Unix style terminal environments an executable must have ./ prepended if it is to be executed from the current directory. This is because the current directory "." is not part of the PATH environmment in order to limit the damage done by malware. Cygwin is simply following this convention, it has nothing per say to do with C++ programs
That's just an issue with your 'path' or 'PATH' variable in your shell. (probably your shell is bash, so it'd be PATH.)
echo $PATH
A typical 'user' path to do what you want would start with "." as a path element. This is a minor security risk of course.
Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 12 years ago.
Improve this question
Possible Duplicate:
Code won’t run. [not]
I have written and compiled a program and i want to make it so that from shell i can just type programname to make it run instead of going to the directory the the program is in and typing ./ before the program name. If this is possible please let me know.
You must learn the ways of the PATH if you're to come with me to Alderaan.
You should add the directory where your compiled program is to your PATH.
For example if you are inside the /home/jimmy/cpp directory
type (leading $ is the prompt)
PATH=$PATH:`pwd`
$myprog
Read about exporting variables and the bashrc file to make this change permanent. (assuming bash as your shell)
A detailed discussion of why putting . (current directory) in the PATH is a bad idea.
Lets say you're being attacked by an adversary on your machine.
He authors a malicious program, and puts it in a directory, hoping that you'll stumble on it eventually. To increase his chances, he names it something common like mv.
If you have added . to the beginning of your path, and happen to be in the right directory when you type mv onefile twofile... then the local mv (./mv) gets run instead of the mv command we're all used too! This happens because . is in your path, and the local mv will be found before the /usr/bin/mv. Suddenly, your user account or the entire machine may be horribly compromised.
(note: mv might be one of the built-in commands, and immune to this. Not sure... but the principle is solid)
So, you learn the lesson, and now put . at the end of your path, so that all "official" directories will be searched before the local directory.
But the attacker is now on to you! Instead of the program mv, he creates in a program mc, which is a common typo for mv. Again, you intend to type mv onefile twofile, but make a simple typo to mc. Now all the "official" directories are searched, the program mc is not found, and finally it is found in the local directory. Malicious code is run, and again you lose.
The lesson is that your PATH should only cover known-good software, and since your current directory changes frequently, you never know exactly what software is there, and should never run it unless you're very explicit about it with the ./ prefix (eg. > ./IMeanToRunThis)
http://ss64.com/bash/alias.html
e.g.
alias progname=/path/to/program/progname
Personally, I use $HOME/bin as a personal collection point for utilities I wrote but that won't be of use to all users. Otherwise, /usr/local/bin is often the right place for locally written programs that are of use to all users. In any case, I have verified that the latter place was on my path and added $HOME/bin as well.
Unless you really are an installer, it is probably not a good idea to go dropping programs into /bin or /usr/bin despite temptation. That would be the moral equivalent of putting your programs in C:\Windows or C:\Windows\System32. It is effectively never the correct answer.
Learning more about the PATH environment variable and how the shell searches for programs to run is definitely recommended. Also, as pointed out in another comment, just don't add . to your PATH because it will come back to haunt you at some point.
Edit: Incidentally, I do a very similar thing on my Windows boxen. I always create a sibling to C:\Program Files named C:\Programs. In there, I make a folder named bin and add that to the system path. I use C:\programs\bin much like I use $HOME/bin on a *nix box, and put any hand-installed (i.e. no real Windows installer was used) programs or stuff ported from *nix that can't tolerate spaces in its path in there in other folders such as C:\Programs\mingw, C:\programs\MSYS, or C:\programs\cygwin.
Any small utilities primarily used from the command prompt usually end up in C:\programs\bin, but for anything I'm seriously planning to use on more than one PC I generally create a real Windows installer with InnoSetup and let it get installed in C:\Program Files.