`command -v` seems to only search in /usr/bin - bash

For some shell script I need to store output of command -v foo in variables. I am checking if some binaries exist on the system. When I execute command -v foo in terminal, I get an output but when I execute command -v foo inside a shell script I don't get any output.
➜ tools git:(install-script) ✗ command -v node
/usr/local/bin/node
check_deps() {
declare -A deps
deps=( ['git']=`command -v git`
['gem']=`command -v gem`
['node']=$(command -v node))
# ['redis-server']=command -v redis-server
# ['postgres']=command -v psql
# ['sass']=command -v sass
# ['gulp']=command -v gulp
# ['bower']=command -v bower )
for each in ${!deps[#]};
do
echo $each ${deps[$each]}
done
}
check_deps
Output is:
node
git /usr/bin/git
gem /usr/bin/gem
[Finished in 0.0s]
What's happening? How do I fix this?

I was using Sublime Text which had a plugin called Bash Build system. Basically it got me a file which didn't have /usr/local/bin, this build syntax now returns proper command -v output:
{
"cmd" : ["bash", "$file"],
"selector" : "source.shell",
"osx": {
"path" : "$PATH:/usr/local/bin"
}
}

Related

How to get the second word of an output from a command in shell?

Hi I am trying to make a shell script.
sudo usermod -s $(whereis -b zsh) $(whoami)
$(whereis -b zsh) makes an error with zsh: command not found zsh:
The error seems to occur because the output of whereis -b zsh is zsh: /usr/bin/zsh /usr/lib/x86_64-linux-gnu/zsh /bin/zsh /etc/zsh /usr/share/zsh /home/linuxbrew/.linuxbrew/bin/zsh
Now I would like to use /usr/bin/zsh for the script as an output. Is there any way to get the second word from the output of whereis -b zsh?
how should the script look like to get what I need?
shell script is quite difficult than I thought. Thank you everyone in advance!
Better add quotes around commands expansion
sudo usermod -s "$(whereis zsh | cut -d ' ' -f2)" "$(whoami)"
Alternate method by getting zsh from the $PATH:
sudo usermod -s "$(command -v zsh)" "$(id -un)"
If you run it under bash:
Instead of parsing the output of whereis, use type:
sudo usermod -s "$(type -P zsh)" "$(whoami)"
Don't forget that type -P yields an empty string, if the program you are searching for is not in the PATH.
If it is not bash, you can also do a
sudo usermod -s "$(which zsh)" "$(whoami)"
Note that which issues an error message if the program can't be found, so if you need an empty output in this case you'll have to throw away stderr.
UPDATE: Thinking of it, IMO a better solution is the one suggested by Lea Gris: command -v is available on bash and POSIX shells, and yields empty output if the file can't be found.
You can do something like:
whereis -b zsh | awk '{print $2}'

Search and replace a specific line with bash

I need add new plugins in my zshrc file using bash script, to do that I search the line which contains plugins = (sometext)
syntax
plugin_text=$(grep "^[^#;]" zshrc | grep -n "plugins=(.*)")
running directly in terminal I get:
$ grep "^[^;]" zshrc | grep -n "plugins=(.*)"
38:# Example format: plugins=(rails git textmate ruby lighthouse)
40:plugins=(git python pip)
40 is the correct line but when I execute my bash script I get:
$ ./config-minimal
3:plugins=(git python pip)
I need change 40 line inserting new plugins. Example:
before
plugins=(git python pip)
after
plugins=(git python pip zsh-autosuggestions zsh-syntax-highlighting)
How can I get this line and replace text with a easy way?
My script
function install_zsh {
# aptitude install zsh
# sh -c "$(wget https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh -O -)"
# Install zsh highlighting
# cd ~/.oh-my-zsh/custom
# git clone https://github.com/zsh-users/zsh-syntax-highlighting.git
# Install zsh auto suggestions
# git clone git://github.com/zsh-users/zsh-autosuggestions
# TODO: Add options in plugins
cd ~
plugin_text=$(grep "^[^#;]" .zshrc | grep -n "plugins=(.*)")
new_plugins=${plugin_text/)/ zsh-autosuggestions zsh-syntax-highlighting)}
line_number=${plugin_text/:plugins*/ }
sed "$(line_number)s/plugin_text/new_plugins/" .zshrc
}
You can handle it with a simple sed:
sed 's/^plugins=(\(.*\)/plugins=(zsh-autosuggestions zsh-syntax-highlighting \1/' .zshrc
Or (thx #123):
sed 's/\(^plugins=([^)]*\)/\1 zsh-autosuggestions zsh-syntax-highlighting/' .zshrc
Add -i flag to infile replacement.
function install_zsh {
# aptitude install zsh
# sh -c "$(wget https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh -O -)"
# Install zsh highlighting
# cd ~/.oh-my-zsh/custom
# git clone https://github.com/zsh-users/zsh-syntax-highlighting.git
# Install zsh auto suggestions
# git clone git://github.com/zsh-users/zsh-autosuggestions
# TODO: Add options in plugins
sed -i.bak 's/^plugins=(\(.*\)/plugins=(zsh-autosuggestions zsh-syntax-highlighting \1/' ~/.zshrc
}

Store the output of shell command in a variable

I am trying to install zfs through shell script while installation I am getting some error so, to automate it fully, I want to get the version to be installed from error itself. For all other commands I am getting the error in one variable but for one command its not coming at all. I tried every solution possible.
I need output of this command
sploutput=$(sudo dkms install -m spl -v $version)
echo $sploutput
echo $sploutput # This is giving nothing.
I tried wrapping it around string also like "sploutput=$(sudo dkms install -m spl -v $version)"
echo "{sploutput}"
Nothing seems to work.
sploutput=$(sudo dkms install -m spl -v $version)
echo $sploutput
it might be because the dkms install outputs on STDERR and not on STDOUT, and with the command you're using, you're only getting STDOUT output in the variable. To take both, you can try:
sploutput=$(sudo dkms install -m spl -v $version 2>&1)
to redirect STDERR into STDOUT.
As per ZMO's answer: try running sudo dkms install -m spl -v $version
See, what is it returning? : STDERR or STDOUT.
In case, if it fails, it won't show up anything in sploutput.
It write only STDOUT to the variable.
Use 2>&1(to write Standard error to standard output).
You can refer IO redirection
You can use following:
sploutput=$(sudo dkms install -m spl -v $version 2>&1)
echo $sploutput

String parsing via ruby (chef)

Need to do install on centos 6 logrotate 3.8.7 out of sources, via chef.
Using simple execute. But also need to check for existing installation. How can I do that thing, if I can't parse logrotate --version output.
logrotate --version | tr -cd [:digit:]
&
logrotate --version | tr -d "logrotate"
and awk - no use..
Even if I don't parse output, chef can't compare it with my variable..
My recipe is:
ver = `logrotate --version`
if ver.eql? "logrotate 3.8.7"
puts "nothing to do"
else
bash "logrotate-source-install" do
user "root"
group "root"
cwd "/tmp"
code <<-EOH
cd /tmp
yum -y install gettext popt-devel
wget https://fedorahosted.org/releases/l/o/logrotate/logrotate-3.8.7.tar.gz
tar xf logrotate-3.8.7.tar.gz
cd logrotate-3.8.7
gmake
gmake install
EOH
end
end
Thx in advance.
Upd.
actual_ver = `logrotate --version 2>&1 | awk '{print $2}'`
ver = "3.8.7"
if actual_ver == ver
puts "nothing to do"
else
bash "logrotate-source-install" do ...
Parsing done, but chef can't recognize output..
You could use attribute only_if to guard this resource for idempotence.
Also, good idea would be to pull version to node attribute like:
default['logrotate']['version'] = '3.8.7'
and then use it in recepie:
version = default['logrotate']['version']
bash "logrotate-source-install" do
user "root"
group "root"
cwd "/tmp"
code <<-EOH
yum -y install gettext popt-devel
wget https://fedorahosted.org/releases/l/o/logrotate/logrotate-#{version}.tar.gz
tar xf logrotate-#{version}.tar.gz
cd logrotate-#{version}
gmake
gmake install
EOH
not_if "[ ${version} = \"$(logrotate --version 2>&1 | awk '{print $2}')\" ]"
end
Better version of this:
bash "logrotate-source-install" do
user "root"
group "root"
cwd "/tmp"
code <<-EOH
cd /tmp
yum -y install gettext popt-devel
wget https://fedorahosted.org/releases/l/o/logrotate/logrotate-3.8.7.tar.gz
tar xf logrotate-3.8.7.tar.gz
cd logrotate-3.8.7
gmake
gmake install
EOH
only_if do
version = shell_out('logrotate --version')
version.error? || version.stdout.split.last != '3.8.7'
end
end
This uses the only_if guard clause to control if the resource converges or not, and uses the shell_out helper instead of Ruby's shell execute syntax. This will be more widely portable, automatically splits stdout and stderr, and will correctly run the install if the command fails. Also doesn't depend on awk.
String parsing via ruby do the thing:
actual_ver = `logrotate --version 2>&1 | awk '{print $2}'`
ver = "387"
if actual_ver.delete('^0-9') == ver
puts "nothing to do"
else
bash "logrotate-source-install" do
user "root"
group "root"
cwd "/tmp"
code <<-EOH
cd /tmp
yum -y install gettext popt-devel
wget https://fedorahosted.org/releases/l/o/logrotate/logrotate-3.8.7.tar.gz
tar xf logrotate-3.8.7.tar.gz
cd logrotate-3.8.7
gmake
gmake install
EOH
end
end

Cannot install gem with Chef for an RVM gemset

I am simply trying to install passenger for nginx but installing the passenger gem fails. Here's what I have in my recipe:
rvm_gem "passenger" do
ruby_string "ruby-1.9.3-p194#env"
action :install
end
# install nginx for rails
execute "passenger_module1" do
user "#{node[:user][:name]}"
environment ({'HOME' => "/home/#{node[:user][:name]}"})
command "rvmsudo passenger-install-nginx-module --auto | bash"
action :run
end
Here's the Error message:
[2012-12-10T01:05:52+00:00] FATAL: Mixlib::ShellOut::ShellCommandFailed: rvm_gem[passenger] (main::default line 127) had an error: Mixlib::ShellOut::ShellCommandFailed: Expected process to exit with [0], but received '1'
---- Begin output of bash -c "source /etc/profile.d/rvm.sh && rvm version | cut -d ' ' -f 2" ----
STDOUT:
STDERR: bash: /etc/profile.d/rvm.sh: No such file or directory
---- End output of bash -c "source /etc/profile.d/rvm.sh && rvm version | cut -d ' ' -f 2" ----
Ran bash -c "source /etc/profile.d/rvm.sh && rvm version | cut -d ' ' -f 2" returned 1
I don't see any issues with your Chef recipe fragment. The error message indicates that the execution of rvm in the shell is failing, because /etc/profile.d/rvm.sh does not exist.
This makes me think that you may not have rvm installed on this node. Did you install rvm on the node?
If you did, did you do it in a way that made it immediately available for use in your Chef run?

Resources