How to stop the execution successive one if preceding one fails when commands are written in line by line by using && operator - bash

I have some commands for installing in shell script.I am Using && for stopping the execution of successive one if the preceding command fails.
for eg:
yum -y install httpd && yum -y install ntp && yum -y install XYZ && yum -y install libxml2-devel.
The execution stops at XYZ because XYZ is not the valid command.
But the problem is when these are written in line by line the && function is not working.
yum -y install httpd &&
yum -y install ntp &&
yum -y install XYZ &&
yum -y install libxml2-devel &&
when the commands are written in this way all libxml2-devel is also executing even XYZ fails.
Any mistake am i doing.?
Please Help.
How to stop the execution successive one if preceding one fails when commands are written in line by line by using && operator.

Drop the last &&; && is a logical operator that joins two commands conditionally, depending on exit status -- the second one will only be run if the first one succeeds (exits with status 0).
You have not used any command after the last &&, so you would get the unexpected end of file error. So, drop the last && (or add something after that):
yum -y install httpd &&
yum -y install ntp &&
yum -y install XYZ &&
yum -y install libxml2-devel

Related

When running my bash script for setting ssh tunneling, it stops half

The following is my bash script setting up ssh tunneling. However, it always stops when it get to the echo part. does anyone know why? My distro is ubuntu 20.
apt update && apt install -y wget && DEBIAN_FRONTEND=noninteractive apt-get install
openssh-server -y &&
mkdir -p ~/.ssh && cd $_ &&
echo "ssh-ed25519
AAAAC3NzaC1lZDI1NTE5AAAAII2AOiMJXSWr/yYuAkSur/QSfdwBbmK3hs4qzlMvOQxT dmml#Dmms-MBP"
>> authorized_keys
&& service ssh start
thanks.
My response would be better placed in a comment, but I can't get the formatting right, so I'll post it here. The problem is likely due to a formatting issue. Splitting the string that's passed to the echo command over multiple lines is especially problematic. Try re-formatting as shown below, noting the backslash (\) at the end of each line. There's likely a better way to accomplish the goal than stringing a large number of commands together. Also, resist the temptation to use "set -e" here. See comments for additional details.
apt update && \
apt install -y wget && \
DEBIAN_FRONTEND=noninteractive apt-get installopenssh-server -y && \
mkdir -p ~/.ssh && \
cd $_ && \
echo "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAII2AOiMJXSWr/yYuAkSur/QSfdwBbmK3hs4qzlMvOQxT dmml#Dmms-MBP" >> authorized_keys && \
service ssh start

apt-get install tzdata noninteractive

When I try to
apt-get install -y tzdata
the command line option for picking timezone shows up. I am trying to use this in a script to do some setup, how can I make the apt-get run without user input?
I know to reconfigure the tzdata I can do
echo "America/New_York" > /etc/timezone
dpkg-reconfigure -f noninteractive tzdata
But when installing I need it to run fully even if it doesn't set the right timezone, I can always reconfigure it.
I tried
echo 5 | apt-get install -y tzdata
but it is not working as expected.
This is the script I used
(Updated Version with input from #elquimista from the comments)
#!/bin/bash
ln -fs /usr/share/zoneinfo/America/New_York /etc/localtime
DEBIAN_FRONTEND=noninteractive apt-get install -y tzdata
dpkg-reconfigure --frontend noninteractive tzdata
Seems to work fine.
As one liner:
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends tzdata
If someone wants to achieve it in Dockerfile, use as below.
RUN DEBIAN_FRONTEND=noninteractive apt-get -y install tzdata
To avoid playing directly with symlinks and to run configuration only once, I suggest to use debconf-set-selections command:
echo 'tzdata tzdata/Areas select Europe' | debconf-set-selections
echo 'tzdata tzdata/Zones/Europe select Paris' | debconf-set-selections
DEBIAN_FRONTEND="noninteractive" apt install -y tzdata
I have recently found the following solution in a Dockerfile building the Cingulata FHE library:
ln -snf /usr/share/zoneinfo/$(curl https://ipapi.co/timezone) /etc/localtime
It basically uses the API provided by ipapi.co to retrieve the timezone information. This automatically configures the timezone properly instead of skipping the dialog and using the default (UTC).
All credit for this should go to #PYA but the right order should be:
ln -fs /usr/share/zoneinfo/America/New_York /etc/localtime
export DEBIAN_FRONTEND=noninteractive
apt-get install -y tzdata
dpkg-reconfigure --frontend noninteractive tzdata
Here is how I did it:
echo 1 > input.txt
echo 1 >> input.txt
apt-get install -y tzdata < input.txt
ln -fs /usr/share/zoneinfo/America/Los_Angeles /etc/localtime
echo America/Los_Angeles > /etc/timezone
The first two echo statements create a text file that contains the selection numbers for the geographic area menu and the city/region menu. This file is then used to provide input to the apt-get install command. The tzdata package will be installed without asking for any user input. The timezone will be set to Africa/Abidjan as if you entered 1 and 1 in response to the prompts you would normally get. Then I change the timezone to what I want with the last two commands.
Instead of 1 and 1, you could use the actual numbers for the geographic area and city/region that you want, but it seems to me that those numbers could change.
here is what worked for me:
from ubuntu:bionic
ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y tzdata
RUN unlink /etc/localtime
RUN ln -s /usr/share/zoneinfo/America/New_York /etc/localtime
After reading the comments, I did two steps below to use the TZ environment variable:
Added the following to the Dockerfile
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends tzdata && apt-get clean
Added the following to the docker CMD script:
if [ ! -z "${TZ}" ]; then
echo "${TZ}" > /etc/timezone
dpkg-reconfigure -f noninteractive tzdata
fi
This worked for me and allowed me to set the time zone when starting the container.

How to execute the multiple commands with && operator in new lines(not all in single line) :shell script

I am Installing multiple packages by using && operator for stopping execution of succeeding one if preceding one fails. && function is working when all written in single line.
But When they written in line by line && function is not working and I am getting error.
My code is like this:
yum -y install XXZ \
&& yum -y install rsync \
&& yum -y install libxml2-devel \
&& yum -y install ntp
The Error is:
install5.sh: line 4: syntax error near unexpected token `&&'
'nstall5.sh: line 4: `&& yum -y install rsync \
How to stop the execution of successive one if preceding one fails by using && operator when the commands are written in line by line(not in a single line).?
Please Help!
$? stores exit code of last command. You can do the following in a script:
yum -y install XXZ
if [[ $? != "0" ]] ## exit code other than zero
then
## your code for failure
exit
fi
yum -y install rsync
if [[ $? != "0" ]]
then
## your code for failure
exit
fi
Do the same for all packages.
I recommend you to make an array and use for loop.
Exit code zero means success. Hope this helped.
yum -y install XXZ &&
yum -y install rsync &&
yum -y install libxml2-devel &&
yum -y install ntp
or
yum -y install XXZ && \
yum -y install rsync && \
yum -y install libxml2-devel && \
yum -y install ntp
I am Using NotePad++. After modifying the EOL Conversion from windows to format to UNIX\OSX. The above code is executed.
Edit --> EOL Conversion --> UNIX\OSX format. and save the document.
Apart from the other solutions, you could also use:
if ! yum -y install XXZ ; then
# command failed, do what you want
exit
fi
if ! yum -y install rsync ; then
# command failed, do what you want
exit
fi
etc.

How to sudo yum install a list of packages only if they are not installed?

I am trying to improve a build script (bash or Makefile) to install some prerequisites if necessary.
I do have a long list of packages (10-15) and I do want to install them only if they are not installed.
As the build script may be run by non root I do want to run sudo yum install only once and only if needed (at least one package is not installed).
My current implementation is clearly not optimal:
for PACKAGE in a b c ... ; do
yum list installed $PACKAGE >/dev/null 2>&1 || sudo yum install -q -y $PACKAGE ;
done
How can I do this?
You could, of course, just put the list of installed packages into a file and run grep against that in a loop, but should you wish to avoid creating any files, running rpm should work:
for p in a b c ... ; do
rpm -q > /dev/null 2>&1 $PACKAGE || sudo yum install -q -y $p
done
When querying package information, rpm returns zero when the package is found and non-zero otherwise.

AWS user-data initial bash script

I was trying to use user data section to initialize EC2 and run some bash scripts on instance startup. Somehow all the scripts are running except the (*) statement. Does anyone know what is happening?
#!/bin/bash
cd /home/ubuntu
apt-get update -y
apt-get -y install nodejs npm build-essential libssl-dev awscli ruby2.0
curl https://raw.githubusercontent.com/creationix/nvm/v0.25.0/install.sh > 123
curl https://raw.githubusercontent.com/creationix/nvm/v0.25.0/install.sh | bash (*)

Resources