Getting error at the time of run .sh script from DockerFile - bash

My DockerFile is :
FROM postgres:latest
VOLUME /var/lib/postgresql/data
ARG PG_POSTGRES_PWD=123qwe
ARG DBUSER=postgres
ARG DBUSER_PWD=123qwe
ARG DBNAME=docker_pg_sh
ARG DB_DUMP_FILE=gtma_latest.sql
ENV POSTGRES_DB docker_pg_sh
ENV POSTGRES_USER postgres
ENV POSTGRES_PASSWORD ${PG_POSTGRES_PWD}
ENV PGDATA /pgdata
COPY wait-for-pg-isready.sh /tmp/wait-for-pg-isready.sh
COPY ${DB_DUMP_FILE} /gtma_latest.sql
RUN set -e && \
nohup bash -c "docker-entrypoint.sh postgres & " && \
/tmp/wait-for-pg-isready.sh && \
psql -U postgres -c "CREATE USER ${DBUSER} WITH SUPERUSER CREATEDB CREATEROLE ENCRYPTED PASSWORD '${DBUSER_PWD}';" && \
psql -U ${DBUSER} -d ${POSTGRES_DB} -c "CREATE DATABASE ${DBNAME} TEMPLATE template0;" && \
pg_restore -v --no-owner --role=${DBUSER} --exit-on-error -U ${DBUSER} -d ${DBNAME} </gtma_latest.sql && \
psql -U postgres -c "ALTER USER ${DBUSER} WITH NOSUPERUSER;" && \
rm -rf /gtma_latest.sql
HEALTHCHECK --interval=30s --timeout=30s --start-period=5s --retries=3 \
CMD pg_isready -U postgres -d docker_pg_sh
and wait-for-pg-isready.sh file is :
#!/bin/bash
set -e
get_non_lo_ip() {
local _ip _non_lo_ip _line _nl=$'\n'
while IFS=$': \t' read -a _line ;do
[ -z "${_line%inet}" ] &&
_ip=${_line[${#_line[1]}>4?1:2]} &&
[ "${_ip#127.0.0.1}" ] && _non_lo_ip=$_ip
done< <(LANG=C /sbin/ifconfig)
printf ${1+-v} $1 "%s${_nl:0:$[${#1}>0?0:1]}" $_non_lo_ip
}
get_non_lo_ip NON_LO_IP
until pg_isready -h $NON_LO_IP -U "postgres" -d "docker_pg_sh"; do
>&2 echo "Postgres is not ready - sleeping..."
sleep 4
done
>&2 echo "Postgres is up - you can execute commands now"
Both file are in same folder.
But when I run the command docker build -t gmta-test-sh-vol:1.0.0 . , I am getting error
like this :
Step 14/15 : RUN set -e && nohup bash -c "docker-entrypoint.sh postgres & " && /tmp/wait-for-pg-isready.sh && psql -U postgres -c "CREATE USER ${DBUSER} WITH SUPERUSER CREATEDB CREATEROLE ENCRYPTED PASSWORD '${DBUSER_PWD}';" && psql -U ${DBUSER} -d ${POSTGRES_DB} -c "CREATE DATABASE ${DBNAME} TEMPLATE template0;" && pg_restore -v --no-owner --role=${DBUSER} --exit-on-error -U ${DBUSER} -d ${DBNAME} </gtma_latest.sql && psql -U postgres -c "ALTER USER ${DBUSER} WITH NOSUPERUSER;" && rm -rf /gtma_latest.sql
---> Running in a791e734c6df
/bin/sh: 1: /tmp/wait-for-pg-isready.sh: not found
The command '/bin/sh -c set -e && nohup bash -c "docker-entrypoint.sh postgres & " && /tmp/wait-for-pg-isready.sh && psql -U postgres -c "CREATE USER ${DBUSER} WITH SUPERUSER CREATEDB CREATEROLE ENCRYPTED PASSWORD '${DBUSER_PWD}';" && psql -U ${DBUSER} -d ${POSTGRES_DB} -c "CREATE DATABASE ${DBNAME} TEMPLATE template0;" && pg_restore -v --no-owner --role=${DBUSER} --exit-on-error -U ${DBUSER} -d ${DBNAME} </gtma_latest.sql && psql -U postgres -c "ALTER USER ${DBUSER} WITH NOSUPERUSER;" && rm -rf /gtma_latest.sql' returned a non-zero code: 127
But there is no error when the line for copy the file wait-for-pg-isready.sh is running .
How can the problem will be solved?
Thanks in advance.

Related

How to rewrite grep in #!/bin/sh?

I have the following shell script, that does not compile:
#!/bin/sh
.....
.....
clean_up() {
echo "Clean up"
docker stop $KC_TEST_SVC
docker stop $KC_NAME
docker stop $POSTGRES_NAME
docker network rm $KC_NETWORK
}
# Check network if exists, if not then create
docker network inspect $KC_NETWORK
if [ $? -eq 1 ]; then
docker network create $KC_NETWORK
if [ $? -eq 1 ]; then
exit 1
fi
fi
docker run -d --rm --name $POSTGRES_NAME \
-e POSTGRES_DB=$POSTGRES_DB \
-e POSTGRES_USER=$POSTGRES_USER \
-e POSTGRES_PASSWORD=$POSTGRES_PW \
--network=$KC_NETWORK \
postgres:12.3
if [ $? -eq 1 ]; then
exit 1
fi
docker build --build-arg STAGE=int --tag $KC_TAG .
if [ $? -eq 1 ]; then
exit 1
fi
docker run -d --rm --name $KC_NAME \
-e DB_VENDOR=POSTGRES \
-e DB_ADDR=$POSTGRES_NAME \
-e DB_DATABASE=$POSTGRES_DB \
-e DB_USER=$POSTGRES_USER \
-e DB_PASSWORD=$POSTGRES_PW \
-e KEYCLOAK_USER=$KC_USER \
-e KEYCLOAK_PASSWORD=$KC_PW \
-e KEYCLOAK_LOGLEVEL=DEBUG \
--network=$KC_NETWORK \
$KC_TAG "-Dkeycloak.migration.action=import -Dkeycloak.migration.provider=dir -Dkeycloak.migration.dir=/opt/jboss/keycloak/import-dir -Dkeycloak.migration.strategy=OVERWRITE_EXISTING"
if [ $? -eq 1 ]; then
exit 1
fi
# Wait until Keycloak get started
sleep 30
# Run test jetty service that is protected with Keycloak
docker run -d --rm --name $KC_TEST_SVC \
-v $(pwd)/app:/app \
--network $KC_NETWORK \
hub.databaker.io/devops/jetty-keycloak:0.1.6
if [ $? -eq 1 ]; then
exit 1
fi
# Request Tokens for credentials
KC_URL=http://$KC_SERVER/$KC_CONTEXT/realms/$KC_REALM/protocol/openid-connect/token
echo "Keycloak URL => $KC_URL"
echo "Test the client connection to Keycloak with user $KC_TEST_USER"
KC_RESPONSE=$(
docker run --rm --network=$KC_NETWORK curlimages/curl:7.71.1 -X POST \
-d "username=$KC_TEST_USER" \
-d "password=$KC_TEST_PW" \
-d "grant_type=password" \
-d "client_id=$KC_TEST_CLIENT" \
$KC_URL | docker run --rm -i stedolan/jq .
)
echo "Response from Keycloak $KC_RESPONSE"
if grep -q "error" <<< "$KC_RESPONSE"; then
echo "++++++++Error+++++++++"
exit 1
fi
KC_ACCESS_TOKEN=$(echo "$KC_RESPONSE" | docker run --rm -i stedolan/jq -r .access_token)
echo "Access token from KC => $KC_ACCESS_TOKEN"
echo "Make request to protected service"
SVC_URL=http://$KC_TEST_SVC:8080/api/health
SVC_RES=$(docker run --rm --network=$KC_NETWORK curlimages/curl:7.71.1 -v -k \
-H "Authorization: Bearer $KC_ACCESS_TOKEN" \
-H "Accept: application/json" \
$SVC_URL | docker run --rm -i stedolan/jq .status)
clean_up
echo "$SVC_RES"
if [ "$SVC_RES" != "I am healthy" ]; then
echo "Test failed."
exit 1
else
echo "Test was successful. The service response $SVC_RES."
fi
it complains:
Syntax error: redirection unexpected
due to of the following line:
if grep -q "error" <<< "$KC_RESPONSE"; then
echo "++++++++Error+++++++++"
exit 1
fi
#!/bin/sh does not support grep. How to rewrite it?
<<< is a here string and it's a bash extension. In posix shell, just pipe the data.
if printf "%s\n" "$KC_RESPONSE" | grep -q "error"; then
Do not do if [ $? -eq 1 ]; then, it's error prone. Do if ! command; then. (You might want to research set -eu).
Change #!/bin/sh to #!/bin/bash (ev. replace bash location, which bash helps to find location of bash, and to see if bash is installed), or you may need to rewrite your script in a portable way. In this case, create a temporary file, put the string in such file, redirect such file to grep (with single <), and then delete the temporary file.
With such long description, you see why there is an extension in bash, on the other hand, it is nearly a syntactic sugar: you can easily do the same.

Script with docker-compose commands. A line is not executed

My script looks like this:
#!/usr/bin/env bash
db_name="dh$1";
db_user="dh$1";
db_backup="dh$1-$2.sql";
docker stop $(docker ps -aq) \
&& docker start platform_db_$1_1 \
&& docker start platform_$1_1 \
&& docker cp $db_backup platform_db_$1_1:/$db_backup \
&& cd ../platform \
&& docker-compose exec db_$1 bash -c "dropdb -U $db_user $db_name && createdb -U $db_user $db_name && psql -U $db_user -d $db_name -f $db_backup" \
&& docker-compose exec $1 php artisan d:d:u \
&& docker-compose exec $1 php artisan settings:sync \
&& docker-compose up -d
Everything works great but the last line docker-compose up -d and probably the one before docker-compose exec $1 php artisan settings:sync don't get executed, and i have no idea why since there are no error messages. Any thoughts?
I believe the question is what can stop a script without error messages.
#Quasimodo for some reason the d:d:u command is stopping the script (after running successfuly). This is the handle method.
Anyways, i've set that command at the end since i don't need it before and all solved. Still I don't know why that happened.
public function handle()
{
$this->checkEnvironment();
$this->info('Pre-migrations');
Artisan::call('migrate', [
'--force' => true,
'--path' => 'database/pre-migrations',
]);
$this->info('Doctrine schema update');
Artisan::call('doctrine:schema:update');
$this->info('Migrations');
Artisan::call('migrate');
$this->info('Done');
}

unable to remove footer for psql ressult in shell script

I have a psql command where I am able to get result but i unable to remove footer
my command
sshpass -p 'password' ssh mptios#xx.xx.xxx.xxx "PGPASSWORD=xxxxx psql -a -h 11.11.111.11 -d TGM_bb_les -U bi_it -t -c \"select count(1) from dwpub.td_bank \" "
my result for above command :-
select count(1) from dwpub.td_bank
29
but I need output as
29
I have tried this command but still unable to get expected output
sshpass -p 'password' ssh mptios#xx.xx.xxx.xxx "PGPASSWORD=xxxxx psql -a -h 11.11.111.11 -d TGM_bb_les -U bi_it --pset\"footer=off\" -c \"select count(1) from dwpub.td_bank \" "
can anyone help me with this
Use grep or egrep to match digits only.
sshpass -p 'password' ssh mptios#xx.xx.xxx.xxx "PGPASSWORD=xxxxx psql -a -h 11.11.111.11 -d TGM_bb_les -U bi_it --pset\"footer=off\" -c \"select count(1) from dwpub.td_bank \" " | grep -Eo '[0-9]+$'
Try with command:
sshpass -p 'password' ssh mptios#xx.xx.xxx.xxx "PGPASSWORD=xxxxx psql -a -h 11.11.111.11 -d TGM_bb_les -U bi_it -t -c \"select count(1) from dwpub.td_bank \" "|tail -1
This will show only the last line

How to properly format an 'if' statement being passed to a remote server in a when using 'while read'?

Ubuntu 18
Bash 4.4.0
I am wanting to pass an if statement to see whether or not a directory exist. If it does, I want to some commands and then a file. I have read through the similar posts but shellcheck complains about my formatting.
Script:
#!/bin/bash
testing="yes"
scriptDir="/root/.work"
wDir="${scriptDir}/.nginx-fix"
if [ "$testing" = "no" ]; then
hostfile="${scriptDir}/.zzz-hostnames"
else
hostfile="${scriptDir}/.zzz-hostnames-tester"
fi
cd "$wDir"
while read fqdn; do
{ clear; echo ""; echo ""; echo "$hostname"; echo ""; }
< /dev/null if ssh -p 34499 root#"${fqdn}" '[ -d /etc/nginx ]'; then
< /dev/null ssh -p 34499 root#"${fqdn}" 'mv /etc/nginx/nginx.conf /etc/nginx/.nginx-sept-30'
< /dev/null scp -P 34499 nginx.conf root#"${fqdn}":/etc/nginx
< /dev/null ssh -p 34499 root#"${fqdn}" 'sed -i "/honeypot/d" /etc/nginx/conf.d/*.conf'
< /dev/null ssh -p 34499 root#"${fqdn}" 'nginx -t'
else
exit 1;
fi
done<"${hostfile}"
Shellcheck complaint:
root#me ~/.work/.nginx-fix # shellcheck .nginx-fixer.sh
In .nginx-fixer.sh line 13:
while read fqdn; do
^-- SC1073: Couldn't parse this while loop.
^-- SC1061: Couldn't find 'done' for this 'do'.
In .nginx-fixer.sh line 15:
< /dev/null if ssh -p 33899 root#"${fqdn}" '[ -d /etc/nginx ]'; then
^-- SC1062: Expected 'done' matching previously mentioned 'do'.
^-- SC1072: Expected "#". Fix any mentioned problems and try again.
I'd appreciate your thoughts.
You can refactor the script to a clearer version and remove all the </dev/null:
while read -r fqdn; do {
{ clear; echo ""; echo ""; echo "$hostname"; echo ""; }
if ssh -p 34499 root#"${fqdn}" '[ -d /etc/nginx ]'; then
ssh -p 34499 root#"${fqdn}" 'mv /etc/nginx/nginx.conf /etc/nginx/.nginx-sept-30'
scp -P 34499 nginx.conf root#"${fqdn}":/etc/nginx
ssh -p 34499 root#"${fqdn}" 'sed -i "/honeypot/d" /etc/nginx/conf.d/*.conf'
ssh -p 34499 root#"${fqdn}" 'nginx -t'
else
exit 1;
fi
} </dev/null; done < "${hostfile}"
Almost invisible to the eye, I have put all the commands inside do ... done inside { .. } </dev/null. That way any command won't read from ${hostfile} and won't mess with while read.
Another option is to use a dedicated file descriptor and pass its number to read:
while read -r -u 10 fqdn; do
{ clear; echo ""; echo ""; echo "$hostname"; echo ""; }
if ssh -p 34499 root#"${fqdn}" '[ -d /etc/nginx ]'; then
ssh -p 34499 root#"${fqdn}" 'mv /etc/nginx/nginx.conf /etc/nginx/.nginx-sept-30'
scp -P 34499 nginx.conf root#"${fqdn}":/etc/nginx
ssh -p 34499 root#"${fqdn}" 'sed -i "/honeypot/d" /etc/nginx/conf.d/*.conf'
ssh -p 34499 root#"${fqdn}" 'nginx -t'
else
exit 1;
fi
done 10<"${hostfile}"
Running the script via 'bash -n' will indicate the 'real' error:
bash -n x.sh
x.sh: line 15: syntax error near unexpected token `then'
x.sh: line 15: ` < /dev/null if ssh -p 34499 root#"${fqdn}" '[ -d /etc/nginx ]' ; then'
You can not place redirection before on the 'if' statement. Move the redirection to the 'ssh' (condition part of the if) command, for example:
# USE:
if ssh < /dev/null -p 34499 root#"${fqdn}" '[ -d /etc/nginx ]' ; then'
# AND NOT:
< /dev/null if ssh -p 34499 root#"${fqdn}" '[ -d /etc/nginx ]' ; then'

Directory exist if [-d "$/root/folder" ]; is not working

I need to create a directory in root directory of Linux if it's not already present in it.So i am using the if [-d "$/root/folder" ]; but it's going to else part even if directory exist. Please help with this. Below is the code-
#! /bin/sh
if [ -d "$/root/folder" ];then
echo "folder file already exist"
else
echo "Settings in progress" \
&& mkdir folder \
&& chmod 7777 folder \
&& cd folder \
&& mkdir FolderConnector \
&& chmod 7777 FolderConnector \
&& cd FolderConnector \
&& mkdir ClientInput \
&& mkdir ClientOutput \
&& chmod 7777 ClientInput \
&& chmod 7777 ClientOutput \
&& cat /home/data/RTV/file2 >>/etc/exports \
&& exportfs -r \
&& exportfs \
&& echo "Settings completed successfully."
fi
What I would do :
#! /bin/sh
set -e
if [ -d "/root/folder" ]; then
echo "folder file already exist"
else
echo "Settings in progress"
mkdir folder
chmod 7777 folde
cd folder
mkdir FolderConnector
chmod 7777 FolderConnector
cd FolderConnector
mkdir ClientInput
mkdir ClientOutput
chmod 7777 ClientInput
chmod 7777 ClientOutput
cat /home/data/RTV/file2 >>/etc/exports
exportfs -r
exportfs
echo "Settings completed successfully."
fi
set -e stop the script on the first error
you had a $ character in your test

Resources