Bash if grep or grep elif grep? So confused - bash

Here is what I am trying to do. I want to grep(maybe?) a file for keywords based on what I find do blah.
if grep "env=" does not exist OR "env=" exists but is null file.name; then
env=prod
elif grep "env=dev" OR "env=qa" file.name; then
env=dev/qa respectivly
I was trying some grep command but was getting stuck with that
Not sure if this gets it yet, still need to test
if ! grep -q -E "^environment=" "${__file}" | grep -q -e "dev|qa|prod"; then
if [ -n "${ENV}" ]; then
echo "environment=${ENV}" >> "${__file}"
else
echo "environment=prod" >> "${__file}"
fi
fi

Use a source command. Put all local variables in file named local_env.sh.
sample content of local_env.sh:
environment=dev
Now you can create a script:
source env.sh
# if environment is empty string set it to prod
[ -z "${environment}" ] && environment=prod
echo ${environment}

Related

Varying Vagrant Vagrants provision script issue

I'm trying to write a provision script for Browscap, and I'm almost there, I just want to see what I'm doing wrong when trying to rewrite php.ini file.
The repo is here.
The provision script looks like this
#!/usr/bin/env bash
# Prettyfiers
BLUE='\033[0;36m'
NC='\033[0m' # No Color
DIR=`dirname $0`
echo "${BLUE}Setting up Browsecap${NC}"
# Check PHP version
PHP_VER=`php -r \#phpinfo\(\)\; | grep 'PHP Version' -m 1 | grep -Po -m 1 '(\d+\.\d+)' | head -1`
MIN_REQ="5.3"
if (( $(echo "${PHP_VER} < ${MIN_REQ}" |bc -l) )); then
echo "${BLUE}The PHP version is lower than 5.3 so browscap won't work. Please upgrade your PHP version to higher than 5.3${NC}"
exit 0
fi
echo "${BLUE}PHP version is${NC}" ${PHP_VER}
BROWSE_INI="/etc/php/${PHP_VER}/mods-available/php_browscap.ini"
# Check if browscap is already installed/set up
if [[ -f "${BROWSE_INI}" ]]; then
echo "${BLUE}Browscap is already installed${NC}"
else
# Set the browscap.ini and the php extension
touch "${BROWSE_INI}"
cp "php_browscap.ini" "${BROWSE_INI}"
echo "${BLUE}Browscap copied${NC}"
fi
PHP_INI="/etc/php/${PHP_VER}/fpm/php.ini"
# Check if php.ini exists before replacing
if [[ -f "${PHP_INI}" ]]; then
echo "${BLUE}php.ini exists${NC}"
# Check if the default value exists - by default it should be ;browscap = extra/browscap.ini
# If it doesn't then find browscap = and replace it with the correct one
if [ "$(grep -qe ";browscap" "${PHP_INI}")" ]; then
sudo sed -i "s|;browscap =|browscap = /etc/php/${PHP_VER}/mods-available/php_browscap.ini|g" "/etc/php/${PHP_VER}/fpm/php.ini"
else
sudo sed -i "s|browscap =|browscap = /etc/php/${PHP_VER}/mods-available/php_browscap.ini|g" "/etc/php/${PHP_VER}/fpm/php.ini"
fi
echo "${BLUE}php.ini changed${NC}"
else
echo "${BLUE}php.ini doesn't exist${NC}"
fi
When the provision ends and I check my php.ini I get
[browscap]
; http://php.net/browscap
;browscap = /etc/php/7.0/mods-available/php_browscap.ini /etc/php/7.0/mods-available/php_browscap.ini extra/browscap.ini
So I'm missing something in my sed command.
But what?
MVE
If you have VVV installed you can go to shh with vagrant ssh
Then go to /home/vagrant and create text.txt and test.sh
text.txt
[browscap]
;browscap = extra/browscap.ini
test.sh
#!/usr/bin/env bash
TEST_FILE="/home/vagrant/text.txt"
# Check if php.ini exists before replacing
if [[ -f "${TEST_FILE}" ]]; then
echo "text.txt exists"
# Check if the default value exists - by default it should be ;browscap = extra/browscap.ini
# If it doesn't then find browscap = and replace it with the correct one
if grep -q ";browscap" "${TEST_FILE}"; then
sudo sed -i "s|;browscap =|browscap = /etc/php/7.0/mods-available/php_browscap.ini|g" "${TEST_FILE}"
else
sudo sed -i "s|browscap =|browscap = /etc/php/7.0/mods-available/php_browscap.ini|g" "${TEST_FILE}"
fi
echo "text.txt changed"
else
echo "text.txt doesn't exist"
fi
This will result in text.txt
[browscap]
browscap = /etc/php/7.0/mods-available/php_browscap.ini extra/browscap.ini
Rewrite this statement
if [ "$(grep -qe ";browscap" "${PHP_INI}")" ]; then
to just
if grep -q ";browscap" "${PHP_INI}"; then
since you can directly use grep's return code in shell conditionals. The reason being in the former case, you are incorrectly checking the return code of grep to see if it succeeded, because the exit code is processed by the shell.
(or) alternatively you could also do
grep -qe ";browscap" "${PHP_INI}"
rc=$?
if [ $rc -eq 0 ]; then
echo 'match found'
fi
because grep returns a different exit code if its found something (zero) vs. if it hasn't found something (non-zero). In an if statement, a zero exit code is mapped to "true" and a non-zero exit code is mapped to false.
Also your sed statement should include the matching part after = which needs to be done as
sed -i "s|;browscap =.*|browscap = /etc/php/${PHP_VER}/mods-available/php_browscap.ini|g" "/etc/php/${PHP_VER}/fpm/php.ini"
Based on the MCVE you posted, you should replace this block of code:
if grep -q ";browscap" "${TEST_FILE}"; then
sudo sed -i "s|;browscap =|browscap = /etc/php/7.0/mods-available/php_browscap.ini|g" "${TEST_FILE}"
else
sudo sed -i "s|browscap =|browscap = /etc/php/7.0/mods-available/php_browscap.ini|g" "${TEST_FILE}"
fi
with just 1 line:
sudo sed -i 's|;?browscap =.*|browscap = /etc/php/7.0/mods-available/php_browscap.ini|' "${TEST_FILE}"

Read unix log for message and then perform action

I am looking to create a shell script to read the message log and when finds the correct string perform an action. So far I have the following:
#!/bin/bash
string="ntp engine ready"
tail -n 0 -f /var/log/messages | \
while read LINE
do
echo "$LINE | grep -q $string"
if [ $? == 0];then
shttpclient "http://127.0.0.1/do/action"
fi
done
But, I get the following error:
grep: engine: No such file or directory
grep: ready: No such file or directory
Even when I see the logger has outputted ntp engine ready.
Firstly, you need to fix your quotes:
echo "$LINE" | grep -q "$string"
Secondly, you can simply do:
if echo "$LINE" | grep -q "$string"; then
rather than checking the return code $? manually. Remember that [ is a command too and if is just checking its return code.
If you do need to use [, remember that ] is an argument to the command so it is essential to surround it with spaces:
if [ $? = 0 ]
I have also removed the second = as it is a bash extension to support it. Actually you are doing an integer comparison, so really it should be one of the following:
if [ $? -eq 0 ] # POSIX compliant
if (( $? == 0 )) # bash arithmetic context
Alter the line as follows:
echo "$LINE" | grep -q "$string"
The quotes were not set correctly. Like when you execute that: grep -q ntp engine ready; ntp is the string to search and engine and ready are the files. It must look like: grep -q "ntp engine ready".

Adding directory to a path variable (like $PATH) just once in bash?

How can I add in bash a test checking if a given directory (say /usr/local/bin) is already in a variable, say $PATH, before actually doing it?
Context: I am creating a script for a package I maintain for which I wish to include all steps to install dependencies. This involves changing the $PATH variable, but my question is more general (changes involve also $PYTHONPATH for instance). However, I wish also to not mingle with the existing variables and to not prepend it if it already exists.
Using grep you can test
echo "$PATH" | grep -o '/usr/local/bin'
Example:
var=$(echo $PATH | grep -o '/usr/local/bin')
if [ -n "$var" ] ; then
echo 'already Existe'
else
echo 'Not exists'
fi
Output:
already Existe
You can check like this:
export p='/usr/local/bin'
(IFS=: a=("$PATH"); printf "%s\n" "${a[#]}"|grep -xq "$p") && echo "exists" || echo "nope"
exists
export p='/usr/local/bin123'
(IFS=: a=("$PATH"); printf "%s\n" "${a[#]}"|grep -xq "$p") && echo "exists" || echo "nope"
nope
grep options used:
-x -> exact match
-q -> quiet, just returns exit status

bash - Comparing variables

I am trying to do the following in bash:
get my external IP
read first line of a file
compare both values
if it is not the same, delete the file and recreate it with the current address
I really don't know why this fails, all my script does is to output my current address and the first line of the file (which by the way is simply "asd" for testing)
#!/bin/bash
IP= curl http://ipecho.net/plain
OLD= head -n 1 /Users/emse/Downloads/IP/IP.txt
if [ "$IP" = "$OLD" ]; then
exit
else
rm /Users/emse/Downloads/IP/IP.txt
$IP> /Users/emse/Downloads/IP/IP.txt
exit
fi
Some obvious problems in your script:
Don't put spaces on either side of equal sign if you want to do assignment
You want the output of curl, head so wrap them in backticks (`)
You want to write $IP into the file, not to execute the content of it as a command, so echo it
The script becomes:
#!/bin/bash
IP=`curl http://ipecho.net/plain`
OLD=`head -n 1 /Users/emse/Downloads/IP/IP.txt`
if [ "$IP" = "$OLD" ]; then
exit
else
rm /Users/emse/Downloads/IP/IP.txt
echo $IP > /Users/emse/Downloads/IP/IP.txt
exit
fi
Excellent answer qingbo, just a tad bit of refinement:
#!/bin/bash
IP=`curl http://ipecho.net/plain`
OLD=`head -n 1 /Users/emse/Downloads/IP/IP.txt`
if [ "$IP" != "$OLD" ]; then
echo $IP > /Users/emse/Downloads/IP/IP.txt # > creates/truncates/replaces IP.txt
fi

Curl not downloading files correctly

So I have been struggling with this task for eternity and still don't get what went wrong. This program doesn't seem to download ANY pdfs. At the same time I checked the file that stores final links - everything stored correctly. The $PDFURL also checked, stores correct values. Any bash fans ready to help?
#!/bin/sh
#create a temporary directory where all the work will be conducted
TMPDIR=`mktemp -d /tmp/chiheisen.XXXXXXXXXX`
echo $TMPDIR
#no arguments given - error
if [ "$#" == "0" ]; then
exit 1
fi
# argument given, but wrong format
URL="$1"
#URL regex
URL_REG='(https?|ftp|file)://[-A-Za-z0-9\+&##/%?=~_|!:,.;]*[-A-Za-z0-9\+&##/%=~_|]'
if [[ ! $URL =~ $URL_REG ]]; then
exit 1
fi
# go to directory created
cd $TMPDIR
#download the html page
curl -s "$1" > htmlfile.html
#grep only links into temp.txt
cat htmlfile.html | grep -o -E 'href="([^"#]+)\.pdf"' | cut -d'"' -f2 > temp.txt
# iterate through lines in the file and try to download
# the pdf files that are there
cat temp.txt | while read PDFURL; do
#if this is an absolute URL, download the file directly
if [[ $PDFURL == *http* ]]
then
curl -s -f -O $PDFURL
err="$?"
if [ "$err" -ne 0 ]
then
echo ERROR "$(basename $PDFURL)">&2
else
echo "$(basename $PDFURL)"
fi
else
#update url - it is always relative to the first parameter in script
PDFURLU="$1""/""$(basename $PDFURL)"
curl -s -f -O $PDFURLU
err="$?"
if [ "$err" -ne 0 ]
then
echo ERROR "$(basename $PDFURLU)">&2
else
echo "$(basename $PDFURLU)"
fi
fi
done
#delete the files
rm htmlfile.html
rm temp.txt
P.S. Another minor problem I have just spotted. Maybe the problem is with the if in regex? I pretty much would like to see something like that there:
if [[ $PDFURL =~ (https?|ftp|file):// ]]
but this doesn't work. I don't have unwanted parentheses there, so why?
P.P.S. I also ran this script on URLs beginning with http, and the program gave the desired output. However, it still doesn't pass the test.

Resources