Bootstrap FreeKB - Linux Commands - which command
Linux Commands - which command

Updated:   |  Linux Commands articles

There are a few commands that can be used to find files on a Linux system.

The which command can be used to determine if a Command Line Interface (CLI) exists in $PATH. For example, which can be used to determine if the java CLI exists in $PATH.

which java

 

If the java CLI does exist in $PATH, something like this should be returned, meaning that the java CLI is located at /usr/bin/java.

/usr/bin/java

 

And the exit code should be 0 (success).

~]# echo $?
0

 

On the other hand, in this example, the which command show that the jar command does not exist in $PATH.

~]$ which jar
/usr/bin/which: no jar in (/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/john.doe/.local/bin:/home/john.doe/bin)

 

And the exit code should be 1 (failed).

~]# echo $?
1

 

The directories being searched are the directories in $PATH.

~]# echo $PATH
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/john.doe/.local/bin:/home/john.doe/bin

 

Let's say the jar command is at /tmp/java/bin/jar. In the /tmp/java/bin directory is not in $PATH, the which command returns "no jar". A temporary solution is to use the export command to add /tmp/java/bin to $PATH.

export PATH=$PATH:/tmp/java/bin

 

And now the which command finds the jar command at /tmp/java/bin/jar.

~]# which jar
/tmp/java/bin/jar

 

Be aware that often, the directories in $PATH are loaded from your users bash profile file, such as /home/john.doe/.bash_profile.

~]$ cat .bash_profile
PATH=$PATH:$HOME/.local/bin:$HOME/bin
export PATH

 

For example, let's say echo returns the following.

~]$ echo $PATH
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/john.doe/.local/bin:/home/john.doe/bin

 

Then if you were to run the following Python script using subprocess and logger to run echo $PATH.

~]$ cat testing.py
#!/usr/bin/python3
import shutil
import logging
import getpass
import sys
import subprocess

log_file="/home/john.doe/testing.log"

logger = logging.getLogger()
logger.setLevel(logging.INFO)
format = logging.Formatter(fmt="[%(asctime)s %(levelname)s] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
fileHandler = logging.FileHandler(log_file)
fileHandler.setFormatter(format)
logger.addHandler(fileHandler)
consoleHandler = logging.StreamHandler(sys.stdout)
consoleHandler.setFormatter(format)
logger.addHandler(consoleHandler)

command="echo $PATH"

stdout, stderr = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()

logging.info(f"PATH = {stdout.decode('utf-8').strip()}")

 

The output should be exactly the same as if you ran the echo $PATH command on the command line.

~]$ python3 testing.py
[2024-04-08 04:44:56 INFO] PATH = /usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/john.doe/.local/bin:/home/john.doe/bin

 

But if you use crontab to run the script.

* * * * * python3 /home/john.doe/testing.py

 

$PATH may only contain /usr/bin and /bin.

[2024-04-08 04:37:01 INFO] stdout = /usr/bin:/bin

 

Which may cause which to return None (if using shutil.which) or stderr if a CLI exists in a $PATH other than /usr/bin and /bin. This occurs because cron jobs run in a minimal environment, and since they're executed directly by crond without a shell (unless you force one to be created), the regular shell setup never happens. One option is to include PATH in crontab, something like this. Be aware that this will apply to every entry in your users crontab.

PATH=/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/john.doe/.local/bin:/home/john.doe/bin

 

Or you could specify the full path to the CLI in shutil.which.

#!/usr/bin/python3
import shutil
response = shutil.which('/usr/local/bin/java')
print(response)

 




Did you find this article helpful?

If so, consider buying me a coffee over at Buy Me A Coffee



Comments


Add a Comment


Please enter d25d6a in the box below so that we can be sure you are a human.