Bash script error: 'which' command not found - bash

The context of my question is a Silverstripe bash script that I'm trying to execute on a Centos 8 OS shell environment. The script is called sake and the relevant code is:
#!/usr/bin/env bash
if ! [ -x "$(command -v which)" ]; then
echo "Error: sake requires the 'which' command to operate." >&2
exit 1
fi
Executing this, either with or without sudo privilege always results in the following error:
Error: sake requires the 'which' command to operate.
My path is:
echo $PATH
/home/hl/.nvm/versions/node/v16.13.0/bin:/home/hl/.local/bin:/home/hl/bin:/usr/share/Modules/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin
which exists:
whereis which
which: /usr/bin/which /usr/share/man/man1/which.1.gz /usr/share/info/which.info.gz
I've tried setting a which alias in .bash_profile to /usr/bin/which, but the alias is the same as the command itself, so this was merely an act of desperation.
Suggestions are greatly appreciated.

Related

Running into error with BASH script with permission denied, but when running the command directly in bash shell its getting executed

When running below command directly in bash shell, I am able to get the output. But when I am passing it via BASH script getting access denied. Any help would be appreciated
$ jq -r '.id' Repooutput.txt
dad04f6d-4e06-4420-b0bc-cb2dcfee2dcf
Error:
$ sh test.sh
test.sh: line 3: /c/ProgramData/chocolatey/bin/jq: Permission denied
I think the reason is that when executing the script with sh test.sh we're asking the POSIX interpreter (shell) to execute the content on the script, while when executing it with ./test.sh we're asking the script to "execute itself".
For the latter, the file needs to have execution permissions, which you can add with
chmod +x test.sh
Issue was with the naming convention of JQ inside BASH folder path, because of which the script was unable to pick the command. Renaming the JQ within BASH folder resolved this

Execute Shell file functions in Mac

I have the following shell file that contains this:
sh
nightlyTag() {
echo $1-alpha.$(date +%Y%m%d).$(($(date +%s%N)/1000000))
}
yarnPubCanaryVersion() {
if [ -z "$1" ]
then
echo "No version argument supplied, maybe you meant v1.0.0?"
return 1
fi
version=`nightlyTag $1`
yarn version --new-version $version --no-git-tag-version
npm publish --tag canary
git reset --hard HEAD
}
I make the file executable with chmod +x canary.sh, then I run it doing ./canary.sh then my terminal changes to sh-3.2$ then I try to run the functions in the terminal like this nightlyTag and I get
sh: nightlyTag: command not found
Same for yarnPubCanaryVersion.
I was looking at this SO question
You won't be able to run functions from the terminal after you run the script.
You need to source the script to do this:
source ./canary.sh
Or add the contents of the file to the .bashrc file or its equivalent, and then source it.
The source command is used to load any function file into the current shell.
Now once you call those functions you will get the expected output.
At the top of your sh file you need to include:
#! /path/to/bash
the path to the bash that you are using.

Basic Bash script results in "edge.sh: line 13: npm: command not found" found issue here but it didn't resolve

The following simple script is apparently not so simple.
The entire script appears to work properly until I get to the npm command.
I have looked at the numerous threads here, but none of the solutions fix the issue.
Each of the scripts is kicked off by a parent script.
Here is the parent:
#!/bin/bash/
authGogglesPath='/c/sandBox/amazon-sandbox/CraigMonroe/platform.shared.auth-goggles'
echo $'\nExecuting node commands for local running solution...\n'
#echo $(pwd)
# run the scripts
bash edge.sh ${edgePath} &
exec bash
I checked my path in the terminal and it's aware
I thought that it might be running as another associated profile so I tried the full path to npm, but the same results.
#!/bin/bash/
authGogglesPath='/c/sandBox/amazon-sandbox/CraigMonroe/platform.shared.auth-goggles'
echo $'\nExecuting node commands for local running solution...\n'
#echo $(pwd)
# run the scripts
bash edge.sh ${edgePath} &
exec bash
That calls edge.sh with a string path for arg (more for later)
edge.sh is another simple script
#!/bin/bash/
PATH=$1
#echo $PATH
if [ -z "${PATH}" ] ; then
"PATH is empty! Aborting"
exit 1
fi
cd "${PATH}"
echo $'\nExecuting Edge...\n'
npm run dev
Each time I run this I'm receiving:
$ bash edge.sh /c/sandBox/amazon-sandbox/CraigMonroe/platform.shared.auth-goggles/
Executing Edge...
edge.sh: line 13: npm: command not found
cmonroe#LP10-G6QD2X2 MINGW64 ~/cruxScripts
$
When in the terminal and manually navigating to the directory and running the command it works properly. Where the edge builds and starts.
Unless npm is in /c/sandBox/amazon-sandbox/CraigMonroe/platform.shared.auth-goggles/, doing PATH=$1 means your PATH only refers to that one folder.
No more /usr/bin or any other folders your bash session might need.
As commented, adding to the PATH should work
PATH="$1:${PATH}"

Execute gcloud commands in a bash script

gcloud init command doesn't offer login prompt during a bash script execution.
But it offered the login after I typed exit command manually after script ended.
vagrant#vagrant-ubuntu-trusty-64:~$ exit
logout
Welcome! This command will take you through the configuration of gcloud.
Settings from your current configuration [default] are:
Your active configuration is: [default]
Pick configuration to use:
[1] Re-initialize this configuration [default] with new settings
[2] Create a new configuration
Please enter your numeric choice: 1
Your current configuration has been set to: [default]
To continue, you must log in. Would you like to log in (Y/n)?
My bash script:
#!/usr/bin/env bash
OS=`cat /proc/version`
function setupGCE() {
curl https://sdk.cloud.google.com | bash
`exec -l $SHELL`
`gcloud init --console-only`
`chown -R $USER:$USER ~/`
}
if [[ $OS == *"Ubuntu"* || $OS == *"Debian"* ]]
then
sudo apt-get -y install build-essential python-pip python-dev curl
sudo pip install apache-libcloud
setupGCE
fi
How can I get the login prompt during the bash script execution?
There are a number of issues with the posted snippet.
The correct snippet is (probably):
function setupGCE() {
curl https://sdk.cloud.google.com | bash
gcloud init --console-only
chown -R $USER:$USER ~/
}
The first error with the original, which you discovered yourself (the what of it at least it not the why), is that exec -l $SHELL is blocking progress. It does that because you've run an interactive shell that is now waiting on you for input and the function is waiting for that process to exit before continuing.
Additionally, exec replaces the current process with the spawned process. You got lucky here actually. Had you not wrapped the call to exec in single quotes your function would have exited the shell script entirely when you exited the $SHELL it launched. As it is, however, exec just replaced the sub-shell that the backticks added and so you were left with a child process that could safely exit and return you to the parent/main script.
The second issue is that backticks run the command they surround and then replace themselves with the output. This is why
echo "bar `echo foo` baz"
outputs bar foo baz, etc. (Run set -x before running that to see what commands are actually being run.) So when you write
`gcloud init --console-only`
what you are saying is "run gcloud init --console-only then take its output and replace the command with that" which will then attempt to run the output as a command itself (which is likely not what you wanted). Similarly on the other lines.
This happens to not have been problematic here though as chown and likely gcloud init don't return anything and so the resulting command line is empty.
Somehow the exec -l $SHELL did all the mess. I changed it to source ~/.bashrc and now it works.

What's wrong with this bash script?

Here's my myscript.sh:
alias apt-get-update="apt-get update -qq"
alias apt-get-install="apt-get install -f -y -qq --force-yes"
alias yum-install="yum --quiet --nogpgcheck -y install"
function ensure_cmd_or_install_package_apt(){
local cmd=$1
shift
local pkg=$*
hash $cmd 2>/dev/null || ( apt-get-update && apt-get-install $pkg )
}
When I run sh myscript.sh I get:
myscript.sh: 5: myscript.sh: Syntax error: "(" unexpected
It looks perfectly fine to me; any ideas?
Does running bash myscript.sh fix it?
It could be your script is running in dash instead of bash.
According to this answer you can change it with the following command:
chsh
Also in general you should be explicit in your script header as to the app/shell you want to run the script with:
#!/bin/bash
If the script requires bash-isms then you should tell it to run with bash.
In your case you are on ubuntu (confirm) and ubuntu uses dash as the default shell (ie /bin/sh is a symlink to dash). Dash doesn't allow:
function name () {}
and instead just wants:
name () {}
In fact the first form should be avoided if possible since it's not portable. But if you use the function keyword, don't use parens since they are not required (it's an accident that it even works).
With regards to setting a script header, sometimes it's better to use env to find the program (say in the case of ruby or perl for instance where you might have numerous ruby/perl executables but the one furthest up on your path is the one you want to run with).
#!/usr/bin/env ruby
Is the way to go. Usually for shells, /bin/bash or /bin/csh etc is sufficient in your shebang, but never assume :).

Resources