0

A BASH script I wrote has two requirements.

At the moment I check if they are installed this way and I thought it was a good solution until I had some complaints from users:

command -v fping >/dev/null 2>&1 || { echo >&2 "Sorry but fping is not installed. Aborting.";  exit 1; }
command -v ifup >/dev/null 2>&1 || { echo >&2 "Sorry but ifupdown is not installed. Aborting.";  exit 1; }

I would like to write this in a way that works for the highest possible numbers of platforms and potential user configuration (a path that doesn't contain /bin or /sbin, for example).

Do you have any suggestion to my check?

Pitto
  • 245
  • 1
    What complaints did you get? – Chris Davies Feb 14 '20 at 20:14
  • 1
    You do realise you can extend the PATH temporarily inside your script, and that you won't get errors adding directories that don't exist. – Chris Davies Feb 14 '20 at 20:15
  • command -v is the best solution. See Why not use “which”? What to use then? – Devon Feb 15 '20 at 08:08
  • @roaima I got one user that did not have sbin in path and therefore the script was not correctly detecting dependencies for him. Honestly his affirmation surprised me a bit too... I am not 100% sure that running command -v fping on ANY machine with ANY configuration will guarantee me that fping is installed and working. – Pitto Feb 15 '20 at 22:09
  • 1
    There is no way to tell if a command is installed. All you can do is see if a command of the correct name can currently be found. You may expect that fping does "fast pings" but someone else might have a program that does "fine picking". – icarus Feb 16 '20 at 09:38
  • Agreed, @icarus Then the way to go would be: find if an executable having the specified name exists and run it and check it behaviour... My question is about the possibility of finding if an executable is installed in the more broad and compatible way for a *nix machine. – Pitto Feb 16 '20 at 20:35
  • "and check it behaviour" - Once you get to that level you would be better off just installing the required program. To push my "fast ping"/"fine picking" example, how do you choose a set of hosts to fast ping? How can you tell the "fine picking" program isn't just a version of fast ping, but with the dns resolver hardcoded to 1.1.1.1 and 9.9.9.9 to avoid the google 8.8.8.8 and 8.8.4.4 and the local servers? See the classic paper https://www.cs.cmu.edu/~rdriley/487/papers/Thompson_1984_ReflectionsonTrustingTrust.pdf as well. – icarus Feb 17 '20 at 01:05
  • @icarus checking a few words / characters from fping localhost / 127.0.0.1 would be enough from my perspective, I guess – Pitto Feb 17 '20 at 10:49
  • this way ignores symbolic links though.. if u install mariadb it will say mysql is installed – cyford Jan 22 '24 at 17:19

2 Answers2

0

I wrote my script same as yours since command function is POSIX compliant. Which complaints did you get from users ?

You probably see this but same question is discussed in How can I check if a program exists from a Bash script?

Paulo Tomé
  • 3,782
-2

You could use 'which' in the same way.

edit:
After some research I'll have to change this suggestion a 'bit'.
While you could use 'which' in the same way, you would end up with the same uncertainties as with other tools (e.g. where, type and even command).
It seems all of those tools could fail in some circumstances to clearly determine the executable started and none (like stated by icarus) can ensure that the executable found is really the one you expect to be installed.

I guess that there isn't a simple cure for your problem and without knowing what complains you got, it's hard to suggest any alternative approaches.

bey0nd
  • 937
  • 1
    which might not even be installed, unlike command -v which is a bash builtin. – icarus Feb 14 '20 at 21:21
  • 1
    what is the output of which cd ? – Jetchisel Feb 14 '20 at 23:50
  • to my knowledge, as cd is a bash bultin, you should only get an exit status of 1. this is obviously only true if no other executable (or a link to an executable) with the name 'cd' was installed/created in any directory included in your $PATH variable. – bey0nd Feb 16 '20 at 15:41
  • any POSIX compliant shell users should avoid which unless you're 100% sure that which is also a builtin from the shell that you're using... – Jetchisel Feb 17 '20 at 00:34