How can I check that program was installed successfully on linux? - linux

I have .bin file, that contains a lot of scripts, that install program on Ubuntu and after installing via terminal
sudo chmod u+x myprogram.bin
./myprogram
I have it in /usr/bin/myprogram.
I need to write the program, which checks if some program was installed correctly to the system. How can I do that ?

Any one of the followings should work
$ command -v foo >/dev/null 2>&1 && echo "installed" || echo "not installed"
$ type foo >/dev/null 2>&1 && echo "installed" || echo "not installed"
$ hash foo >/dev/null 2>&1 && echo "installed" || echo "not installed"
In your case you may use
$ command -v /usr/bin/myprogram >/dev/null 2>&1 && echo "installed" || echo "not installed"
or else you can create function like below
#!/usr/bin/env bash
installed()
{
command -v "$1" >/dev/null 2>&1
}
# and then
if installed ls; then
echo 'ls exists'
else
echo 'ls not installed'
fi
Examples :
$ command -v ls >/dev/null 2>&1 && echo "installed" || echo "not installed"
installed
$ command -v foo >/dev/null 2>&1 && echo "installed" || echo "not installed"
not installed
If you already know the full path to the application/program then any one of the following should work
$ test -x /bin/ls && echo 'installed' || echo 'not installed'
installed
$ [ -x /bin/ls ] && echo 'installed' || echo 'not installed'
installed

Related

How to check if a file with a certain string in its filename exists in bash?

I want to print out an error message if a file with a "RDR_Config_Summary" in its filename does not exist in the directory. Some example filenames could be er2_FCLS_RDR_Config_Summary.txt or er1_CDMA_RDR_Config_Summary.txt. I am getting a syntax error for the following code:
cd $inputDir/$reviewDir
[[ ! grep "RDR_Config_Summary" ]] && echo -e "\nError: RDR Config Summary file was not found\n" && exit 1
cd $inputDir/$reviewDir
ls | grep "RDR_Config_Summary" > /dev/null 2>&1
[ $? -ne 0 ] && echo -e "\nError: RDR Config Summary file was not found\n" && exit 1
[[ is a command itself; you don't need it to run grep. However, you have nothing to run grep on. Use pathname expansion instead.
cd "$inputDir/$reviewDir"
shopt -s failglob
if ! { : *RDR_ConfigSummary*; } 2> /dev/null; then
echo -e "\nError: RDR Config Summary file was not found\n";
exit 1
fi
shopt -u failglob

Creating an RPM with CMake will result in unusable system

Currently I am moving my packaging from a bunch of weird scripts into CMake using CPack. The Debian and TGZ work really nice but the RPM is giving me troubles... When I install the RPM that has been created on openSUSE 15.1 then it will result in an unusable system (no even ls can be executed anymore and I cannot dig into why as of not beeing able to open a konsole or something).
Here is my CPack code (ive stripped anything with DEB and TGZ for readability):
set(CPACK_GENERATOR "DEB;TGZ;RPM")
# Common packaging params
set(CPACK_PACKAGE_NAME "mytool")
set(VERSION "${ver_maj}.${ver_min}.${ver_build}")
set(CPACK_PACKAGE_VERSION ${VERSION})
set(CPACK_SET_DESTDIR true)
# RPM packaging params
set(CPACK_RPM_PACKAGE_SUMMARY "Summary")
set(CPACK_RPM_PACKAGE_NAME "mytool")
set(CPACK_RPM_PACKAGE_VERSION "${VERSION}")
set(CPACK_RPM_PACKAGE_LICENSE "Proprietary")
set(CPACK_RPM_PACKAGE_GROUP "Applications/Internet")
set(CPACK_RPM_PACKAGE_VENDOR "me, myself and I")
set(CPACK_RPM_PACKAGE_URL "https://myurl555.com/")
set(CPACK_RPM_PACKAGE_DESCRIPTION "MyDesc")
set(CPACK_RPM_POST_INSTALL_SCRIPT_FILE "${CMAKE_SOURCE_DIR}/make/rpm/post")
set(CPACK_RPM_POST_UNINSTALL_SCRIPT_FILE "${CMAKE_SOURCE_DIR}/make/rpm/postun")
set(CPACK_RPM_PRE_UNINSTALL_SCRIPT_FILE "${CMAKE_SOURCE_DIR}/make/rpm/preun")
The post script:
if [ -x %{_bindir}/gtk-update-icon-cache-2.0 ]; then
%{_bindir}/gtk-update-icon-cache-2.0 %{_datadir}/icons/hicolor > /dev/null 2>&1 || true
fi
if [ -x %{_bindir}/gtk-update-icon-cache ]; then
%{_bindir}/gtk-update-icon-cache %{_datadir}/icons/hicolor > /dev/null 2>&1 || true
fi
SYSTEMD=`pidof systemd || echo '0'`
if [ "${SYSTEMD}" != "0" ]; then
if [ -e /etc/systemd/system/mytool.service ]; then
rm /etc/systemd/system/mytool.service
fi
cp /usr/share/mytool/files/systemd/mytool.service /etc/systemd/system/mytool.service
systemctl daemon-reload
systemctl enable mytool
fi
service mytool start
if [ -x %{_bindir}/update-desktop-database ]; then
%{_bindir}/update-desktop-database > /dev/null 2>&1 || true
fi
postun:
if [ -x %{_bindir}/gtk-update-icon-cache-2.0 ]; then
%{_bindir}/gtk-update-icon-cache-2.0 %{_datadir}/icons/hicolor > /dev/null 2>&1 || true
fi
if [ -x %{_bindir}/gtk-update-icon-cache ]; then
%{_bindir}/gtk-update-icon-cache %{_datadir}/icons/hicolor > /dev/null 2>&1 || true
fi
SYSTEMD=`pidof systemd || echo '0'`
if [ "${SYSTEMD}" != "0" ]; then
systemctl daemon-reload
fi
preun:
service mytool stop > /dev/null 2>&1 || true
SYSTEMD=`pidof systemd || echo '0'`
if [ "${SYSTEMD}" != "0" ]; then
systemctl disable mytool > /dev/null 2>&1 || true
rm /etc/systemd/system/mytool.service
fi
I cannot see any reason why something like this happens. What happens to the system is that when using alt+f2 and running for example konsole then it will tell me that it cannot make konsole executable. The executable /usr/bin/konsole is still there, the groups of the user did not change, etc.

Bash if condition to check if a ubuntu package has a newer version?

I need a bash line to check if a ubuntu package needs an upgrade or not.
For example, I want to check if the package 'firefox' needs an upgrade using dpkg or apt-get commands.
Hypthetical Example:
# Hypothetical example pseudo-code
if [[ $(firefox_needs_upgrade) ]]; then echo "Firefox needs upgrading";fi
This should work for you:
#!/bin/bash
PACKAGE="firefox"
TMP_FILE="/tmp/upgrade_list"
apt-get -yqq update
apt-get -sqq upgrade | grep Inst > ${TMP_FILE}
grep -qi ${PACKAGE} ${TMP_FILE}
if [ $? == 0 ]
then
echo "${PACKAGE} needs to be upgraded"
fi
Following command would help you :-
/usr/lib/update-notifier/apt-check --human-readable
or
cat /var/lib/update-notifier/updates-available
For more details you can check the link below :-
https://askubuntu.com/questions/49958/how-to-find-the-number-of-packages-needing-update-from-the-command-line
Thanks & Regards,
Alok Thaker
Bash function:
apt_needs_upgrade() {
NEEDS_UPGRADE=$(/usr/lib/update-notifier/apt-check -p 2>&1 >/dev/null | grep "^$1$" | wc -l)
if [ "$NEEDS_UPGRADE" == 1 ]; then
return 0; # 0 means true in bash!!!
else
return 1; # false
fi;
}
Use it:
if apt_needs_upgrade "firefox"; then
echo "Needs upgrading"
else
echo "No need to upgrade"
fi;
Ok edited my answer with a tested code. It's maybe a more pretty way to do it :
#retrieving info about the package
dpkg -l $1 >/dev/null
if [ $? -ne 0 ]
then
echo "$1 not installed or issue retrieving informations"
exit
else
#We check if pkg is upgradable
UPGRADABLE=$(apt-get -s upgrade -u | egrep -c "^Conf $1 |^Inst $1 ")
if [ $UPGRADABLE -gt 0 ]
then
echo "$1 need an upgrade"
else
echo "$1 up to date"
fi
fi
usage :
# /tmp/check.sh openssh-server
openssh-server need an upgrade

Chained && and || operators in bash scripting

I want to execute a series of commands in a bash script.
If any fail, the script should echo a line describing which line failed, and then exit the function.
Currently, my script echos the output adequately, but doesn't exit the script (because the echo command returns 0).
I have
COMMAND_A || echo "command A failed" | tee -a $SUMMARY_FILE
COMMAND_B || echo "command B failed" | tee -a $SUMMARY_FILE
COMMAND_C || echo "command C failed" | tee -a $SUMMARY_FILE
but these have no dependence on the previous line - I think enclosing with bash -e would also not help, since then either COMMAND_A failing would exit without the echo, or else the echo would succeed and nothing would exit.
Since the echo will succeed, I can't just add && to each line.
I could perhaps use
{ COMMAND_A && \
{ COMMAND_B && \
{ COMMAND_C || echo "C failed" | tee -a $SUM } \
|| echo "B failed" | tee -a $SUM } \
|| echo "A failed" | tee -a $SUM }
but this seems very clunky.
Is there a better syntax/style/method?
For a concrete example:
cmake -DCMAKE_INSTALL_PREFIX=$PREFIX -DCMAKE_BUILD_TYPE=Release .. || \
echo "$(date +%d/%m/%y-%H:%M:%S): cmake failed for $1" | tee -a $SUMFILE
make -j16 || \
echo "$(date +%d/%m/%y-%H:%M:%S): make failed for $1" | tee -a $SUMFILE
sudo make install && \
echo "$(date +%d/%m/%y-%H:%M:%S): Installed $1" | tee -a $SUMFILE || \
echo "$(date +%d/%m/%y-%H:%M:%S): make install failed for $1" | tee -a $SUMFILE
Edit
I can perhaps get some improvement with
COMMAND_A || { echo "A failed" && false; } && \
COMMAND_B || { echo "B failed" && false; } && \
COMMAND_C && echo "C succeeded" || { echo "C failed" && false; }
but this will still print that A, B and C failed if A fails (even though the commands are short-circuited, hence the improvement)
Since the series of commands is executed within a function, the return statement can be used.
If this were not the case, exit may be the appropriate choice.
Consequently, I can use the idea in the question's edit to write:
standardInstall() {
# Should be passed the directory (ie application/library) name as
# an argument.
if [ -z "$1" ]; then
echo "No argument was passed to standardInstall()"
echo "Exiting"
exit 2
fi
pushd $1/build/
cmake -DCMAKE_INSTALL_PREFIX=$KF5 -DCMAKE_BUILD_TYPE=Release .. || \
{ echo "$(date +%d/%m/%y-%H:%M:%S): cmake failed for $1" \
| tee -a $SUMFILE && return 1; } && \
make -j16 || \
{ echo "$(date +%d/%m/%y-%H:%M:%S): make failed for $1" \
| tee -a $SUMFILE && return 1; } && \
sudo make install && \
echo "$(date +%d/%m/%y-%H:%M:%S): Installed $1" | tee -a $SUMFILE || \
{ echo "$(date +%d/%m/%y-%H:%M:%S): make install failed for $1" \
| tee -a $SUMFILE && return 1; }
popd
}

A universal bash script for installing with apt-get and yum

I'm trying to write a simple bash wrapper which abstracts yum and apt-get. Basically so we can do something like universal-install curl Here is what I have so far:
# universal-install
package=$1
apt=`command -v apt-get`
yum=`command -v yum`
if [ -n "$apt" ]; then
apt-get update
apt-get -y install $package
elif [ -n "$yum" ]; then
yum -y install $package
else
echo "Err: no path to apt-get or yum" >&2;
exit 1;
fi
Are there any errors or improvements/optimizations that can be made?
Take a look at how pacapt detects the OS:
# Detect package type from /etc/issue
_found_arch() {
local _ostype="$1"
shift
grep -qis "$*" /etc/issue && _OSTYPE="$_ostype"
}
# Detect package type
_OSTYPE_detect() {
_found_arch PACMAN "Arch Linux" && return
_found_arch DPKG "Debian GNU/Linux" && return
_found_arch DPKG "Ubuntu" && return
_found_arch YUM "CentOS" && return
_found_arch YUM "Red Hat" && return
_found_arch YUM "Fedora" && return
_found_arch ZYPPER "SUSE" && return
[[ -z "$_OSTYPE" ]] || return
# See also https://github.com/icy/pacapt/pull/22
# Please not that $OSTYPE (which is `linux-gnu` on Linux system)
# is not our $_OSTYPE. The choice is not very good because
# a typo can just break the logic of the program.
if [[ "$OSTYPE" != "darwin"* ]]; then
_error "Can't detect OS type from /etc/issue. Running fallback method."
fi
[[ -x "/usr/bin/pacman" ]] && _OSTYPE="PACMAN" && return
[[ -x "/usr/bin/apt-get" ]] && _OSTYPE="DPKG" && return
[[ -x "/usr/bin/yum" ]] && _OSTYPE="YUM" && return
[[ -x "/opt/local/bin/port" ]] && _OSTYPE="MACPORTS" && return
command -v brew >/dev/null && _OSTYPE="HOMEBREW" && return
[[ -x "/usr/bin/emerge" ]] && _OSTYPE="PORTAGE" && return
[[ -x "/usr/bin/zypper" ]] && _OSTYPE="ZYPPER" && return
if [[ -z "$_OSTYPE" ]]; then
_error "No supported package manager installed on system"
_error "(supported: apt, homebrew, pacman, portage, yum)"
exit 1
fi
}
As you can see it first checks /etc/issue, then failing that the script looks for the associated executable file for each package manager.
But heck, why not just use pacapt, instead of rolling your own?
If you're going to do this, why require the user to tell the script which tool to use?
#!/bin/bash
# Find our package manager
if VERB="$( which apt-get )" 2> /dev/null; then
echo "Debian-based"
elif VERB="$( which yum )" 2> /dev/null; then
echo "Modern Red Hat-based"
elif VERB="$( which portage )" 2> /dev/null; then
echo "Gentoo-based"
elif VERB="$( which pacman )" 2> /dev/null; then
echo "Arch-based"
else
echo "I have no idea what I'm doing." >&2
exit 1
fi
if [[ 1 -ne $# ]]; then
echo "Syntax: $0 PACKAGE"
exit 1
fi
$VERB "$1"
exit $?
Slightly better would to to look at /etc/issue to see what your distribution is and behave accordingly.
I was looking for a one-liner to install a package and couldn't find any so this was my final version:
if [ "" == "`which unzip`" ]; then echo "Unzip Not Found"; if [ -n "`which apt-get`" ]; then apt-get -y install unzip ; elif [ -n "`which yum`" ]; then yum -y install unzip ; fi ; fi
It's specific for the unzip package, but can be altered to any other package that is available on apt-get/yum.
Hope this will help someone :)
#!/bin/bash
# file: src/bash/aspark-starter/install-prerequisites-for-aspark-starter.sh
# caveat package names are for Ubuntu !!!
set -eu -o pipefail # fail on error , debug all lines
# run as root
[ "${USER:-}" = "root" ] || exec sudo "$0" "$#"
echo "=== $BASH_SOURCE on $(hostname -f) at $(date)" >&2
echo installing the must-have pre-requisites
while read -r p ; do
if [ "" == "`which $p`" ];
then echo "$p Not Found";
if [ -n "`which apt-get`" ];
then apt-get install -y $p ;
elif [ -n "`which yum`" ];
then yum -y install $p ;
fi ;
fi
done < <(cat << "EOF"
perl
zip unzip
exuberant-ctags
mutt
libxml-atom-perl
postgresql-9.6
libdbd-pgsql
curl
wget
libwww-curl-perl
EOF
)
echo installing the nice-to-have pre-requisites
echo you have 5 seconds to proceed ...
echo or
echo hit Ctrl+C to quit
echo -e "\n"
sleep 6
echo installing the nice to-have pre-requisites
while read -r p ; do
if [ "" == "`which $p`" ];
then echo "$p Not Found";
if [ -n "`which apt-get`" ];
then apt-get install -y $p ;
elif [ -n "`which yum`" ];
then yum -y install $p ;
fi ;
fi
done < <(cat << "EOF"
tig
EOF
)

Resources