I'm pretty new to programming for Linux environments, so I don't exactly know what to search for in order to answer this question for myself. I need to understand how applications set the shell to accept a certain command to start them. For example, you can start Firefox from the command line by executing the command: firefox.
I don't know where this is defined. Makefile? Configure script? In the source code itself?
Any resources / reading on Linux programming tidbits like these would be greatly appreciated!
Thank you.
Firefox is launched by the command "firefox" because there is an executable file in one of the folders in the $PATH environment variable called "firefox".
Are you talking about the PATH variable? It seems like you are.
In linux, you should be able to type: "echo $PATH" (without quotes) and get a ":"-separated list of locations where programs are located (like firefox).
If you need to add something to your path, you should be able to do:
export PATH=$PATH:/another/directory
In your shell (which is most likely bash)
You can also type:
which firefox
To display the location of the firefox executable.
Typically the shell is going to have an environment variable called $PATH set. This is just an ordered list of all the directories to look when somebody types in a command. As soon as it finds an executable file (by which I mean a file for which you have execute permissions, not a file ending in .exe) with the same name as whatever was typed, it will run that file. Common directories in $PATH might be /bin, /usr/local/bin, ~/bin, etc.
So, when you type 'firefox', the shell looks through all the directories in $PATH until it finds /usr/local/bin/firefox, which it then runs. To make your own programs run the same way, you'll either need to put them (or a symbolic link to them) in a directory that is likely to be in every user's path (/usr/local/bin/ is a good choice), or you'll need to get your users to add your program's directory to their $PATH.
For a more complete description, see the Wikipedia article about the $PATH variable.
As an alternative to the modification of $PATH mentioned earlier, you could also copy or link your executable in one of the directories already in your $PATH. more specifically, /usr/local/bin/ is available on most UNIX system for pretty much this purpose (installing software outside the default package management of the operating system).
It has to be in the path as everyone else mentioned, but you might also need to make it executable with something like this:
chmod +x /path/to/file
And if it's a script there's usually a shebang at the top that tells the os what to use to execute it:
#! /usr/bin/python
Often, large packages are installed in /opt with a wrapper script or link somewhere in the PATH. For example, on my system, Google Picasa is installed in /opt/google/picasa and there is a symlink at /usr/bin/picasa to /opt/google/picasa/3.0/picasa
Firefox is at /usr/bin/firefox on my system and that's a symlink to /usr/bin/firefox-3.0 which is itself a symlink to /usr/lib/firefox-3.0.11/firefox.sh - That shell file fumbles around until it finally runs /usr/lib/firefox-3.0.11/firefox (unless it finds a reason to do something else). That, finally, is a binary executable. So /usr/lib is where firefox is installed, for me.
You can use this command to find out where a program is:
type -a firefox
Then, you can find out what kind of file it is using this:
file /usr/bin/firefox
Also see the Filesystem Heirarchy Standard for more information about recommended locations for files and programs.
Related
I feel like I'm missing something very basic so apologies if this question is obtuse. I've been struggling with this problem for as long as I've been using the bash shell.
Say I have a structure like this:
├──bin
├──command (executable)
This will execute:
$ bin/command
then I symlink bin/command to the project root
$ ln -s bin/command c
like so
├──c (symlink to bin/command)
├──bin
├──command (executable)
I can't do the following (errors with -bash: c: command not found)
$ c
I must do?
$ ./c
What's going on here? — is it possible to execute a command from the current directory without preceding it with ./ and also without using a system wide alias? It would be very convenient for distributed executables and utility scripts to give them one letter folder specific shortcuts on a per project basis.
It's not a matter of bash not allowing execution from the current directory, but rather, you haven't added the current directory to your list of directories to execute from.
export PATH=".:$PATH"
$ c
$
This can be a security risk, however, because if the directory contains files which you don't trust or know where they came from, a file existing in the currently directory could be confused with a system command.
For example, say the current directory is called "foo" and your colleague asks you to go into "foo" and set the permissions of "bar" to 755. As root, you run "chmod foo 755"
You assume chmod really is chmod, but if there is a file named chmod in the current directory and your colleague put it there, chmod is really a program he wrote and you are running it as root. Perhaps "chmod" resets the root password on the box or something else dangerous.
Therefore, the standard is to limit command executions which don't specify a directory to a set of explicitly trusted directories.
Beware that the accepted answer introduces a serious vulnerability!
You might add the current directory to your PATH but not at the beginning of it. That would be a very risky setting.
There are still possible vulnerabilities when the current directory is at the end but far less so this is what I would suggest:
PATH="$PATH":.
Here, the current directory is only searched after every directory already present in the PATH is explored so the risk to have an existing command overloaded by an hostile one is no more present. There is still a risk for an uninstalled command or a typo to be exploited, but it is much lower. Just make sure the dot is always at the end of the PATH when you add new directories in it.
You could add . to your PATH. (See kamituel's answer for details)
Also there is ~/.local/bin for user specific binaries on many distros.
What you can do is add the current dir (.) to the $PATH:
export PATH=.:$PATH
But this can pose a security issue, so be aware of that. See this ServerFault answer on why it's not so good idea, especially for the root account.
How do developers usually deal with different paths for executable files?
My program is currently in /usr/local/bin and I am wondering how to make it work weather it is in /usr/local/bin or in /usr/bin while being able to access the config files from one of the etc folders (depends on the executable path).
I can't just use relative paths because I need to make it relative to the path of the executable file and even then, it wouldn't be enough because I would need to access /etc weather than /usr/local/etc.
Is there a common way to deal with this situation? Is it dealt with during the installation? Do I need to make a different version of my program for the local and for the global path?
In a shell script, you can detect the executable path of the script with
dirname `readlink -f $0`
and work with that.
If you run your program as root, then it should be able to access the configuration files on /etc/ or any other place without a problem. You could grep it from the script or whatever you need.
If your program is not run as root, then you should make sure that the configuration file being accessed on /etc/ gives the user the right to read it. See chmod man for more information.
Finally, your script should run fine from any of the locations you mentioned, although /usr/local/bin/ is generally where locally developed scripts should go. Just call your script by its full path and it will work: ex: /usr/local/bin/script
Note: don't forget to make your script executable: chmod +x /usr/local/bin/script
At first I had
touch $NAME_OF_FILE$DATE.$FILE_EXT
then I changed it to
PATH="Logs/"
touch $PATH$NAME_OF_FILE$DATE.$FILE_EXT
The file is created correctly in the folder, however only echos are being printed in there because says commands are not found like grep, awk, and others.
EDIT: The folder is already created on my desktop
Thanks
Alan
PATH is an environment variable that specifies where executables are located and is used by your shell to look for commands executables (grep, awk, ...). You should not override it in your script.
Try:
MYPATH="Logs/"
touch $MYPATH$NAME_OF_FILE$DATE.$FILE_EXT
To understand what PATH is open a shell and type echo $PATH. You will see it contains the directories where your commands executables are.
I know how to run the script I created. But it is a matter of pain that I need to change directory through terminal and run my scripts.
I need to run the slowloris script, that has into Desktop, now change directory to Desktop and run.
Then I have another in root; now change the directory to root and run that.
My question is:
How can I run any shell-script by just typing ./script from any path like we start Metasploit from any path by giving msfconsole from any path.
One option is simply to type the path to the script:
~/Desktop/script
This works fine, but gets a bit unwieldy.
This is what the PATH environment variable is for. And it is what $HOME/bin is for.
Create yourself a directory $HOME/bin. Put all your executable scripts in it (make them executable with chmod +x script if need be††). This way, there's one place to look for the scripts you want to run.
Add $HOME/bin to your PATH. I put mine at the front: PATH="$HOME/bin:$PATH, but you could put it at the back if you prefer.
Update your .profile or .bash_profile (or possibly .bashrc) file to set PATH. Beware of a continually growing PATH, though.
As tripleee noted, once the command is installed in a directory on PATH, you no longer type ./script, but just script. This is exactly like you type ls and not /bin/ls, etc. Once the program is installed in a directory on your PATH, it is (for many purposes) indistinguishable from a system-provided command.
I have about 500 scripts and programs in my $HOME/bin directory.
Note that this doesn't require any special privileges. If you have administrator access to your machine and you think other users might find your commands useful, then you could install the scripts/programs in one of the system-provided directories on your PATH. However, it is usually best not to add programs to any of:
/bin
/usr/bin
/sbin
/usr/sbin
There is often/usually /usr/local/bin which is a suitable place for widely used commands not provided by the system.
†† It would be better to use chmod a+x,go-w script; your scripts should not be writable by other people. You could even simply use chmod 555 script or chmod 755 script. I tend to keep my scripts non-writable. That way, I have to go through a formal change process with the version control system. It means there's less danger of uncontrolled changes.
You have to copy or link the script into a directory that is on the $PATH. Usually /usr/bin and /usr/local/bin/ are on the path so these are good locations to link or copy the script to.
ln -s /path/to/your/script /usr/local/bin
If you are not root you will either need to sudo that command or run it as the root user.
I'm rubbish at Linux, so this is probably an easy question...
I want the executable here:
/root/hiphop/hiphop-php/src/hphp/hphp
To be run when I type:
hphp
How do I set that?
alias hphp=/root/hiphop/hiphop-php/src/hphp/hphp
The environment variable called PATH will tell your shell where to look for executables. If you add a line like this:
export PATH=$PATH:/root/hiphop/hiphop-php/src/hphp
to your bashrc ( assuming you're using bash )
then that directory will be scanned for executables every time you enter something on the command line.
alternately, you could add a symlink from a location already in your PATH to that file ( which is probably a better idea ).
ln -s /root/hiphop/hiphop-php/src/hphp/hphp /usr/sbin/hphp
EDIT: also it looks like this is a program you've compiled yourself via configure/make (or similar). there is probably a make target called install which you can use to copy the file to /usr/local/sbin ( or something like that ). you will need to be root though.