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}"
Related
I am a beginner and trying to write a script that takes a config file (example below) and sets the rights for the users, if that user or group doesn´t exist, they get added.
For every line in the file, I am cutting out the user or the group and check if they exist.
Right now I only check for users.
#!/bin/bash
function SetRights()
{
if [[ $# -eq 1 && -f $1 ]]
then
for line in $1
do
var1=$(cut -d: -f2 $line)
var2=$(cat /etc/passwd | grep $var1 | wc -l)
if [[ $var2 -eq 0 ]]
then
sudo useradd $var1
else
setfacl -m $line
fi
done
else
echo Enter the correct path of the configuration file.
fi
}
SetRights $1
The config file looks like this:
u:TestUser:- /home/temp
g:TestGroup:rw /home/temp/testFolder
u:TestUser2:r /home/temp/1234.txt
The output:
grep: TestGroup: No such file or directory
grep: TestUser: No such file or directory
"The useradd help menu"
If you could give me a hint what I should look for in my research, I would be very grateful.
Is it possible to reset var1 and var2? Using unset didn´t work for me and I couldn´t find variables could only be set once.
It's not clear how you are looping over the contents of the file -- if $1 contains the file name, you should not be seeing the errors you report.
But anyway, here is a refactored version which hopefully avoids your problems.
# Avoid Bash-only syntax for function definition
SetRights() {
# Indent function body
# Properly quote "$1"
if [[ $# -eq 1 && -f "$1" ]]
then
# Read lines in file
while read -r acl file
do
# Parse out user
user=${acl#*:}
user=${user%:*}
# Avoid useless use of cat
# Anchor regex correctly
if ! grep -q "^$user:" /etc/passwd
then
# Quote user
sudo useradd "$user"
else
setfacl -m "$acl" "$file"
fi
done <"$1"
else
# Error message to stderr
echo Enter the correct path of the configuration file. >&2
# Signal failure to the caller
return 1
fi
}
# Properly quote argument
SetRights "$1"
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}
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
I am trying to replace some strings in a file with sed and I'm getting a strange error.
Here is the script...
#!/bin/bash
TEMPLATE=/etc/nginx/site-template
if [ -f $TEMPLATE ]; then
echo -n
else
echo "Template $TEMPLATE not found."
exit
fi
function usagehelp {
echo "Usage: DOMAIN SITEDIR"
echo "Example: createsite.sh test.com /var/www/sites/site"
}
if [ -z $1 ]; then
usagehelp
exit
fi
if [ -z $2 ]; then
usagehelp
exit
fi
SDOMAIN=$1
SDIR=$2
if [ -f /etc/nginx/sites-enabled/$SDOMAIN ]; then
echo "Site already exists!"
exit
fi
SCONFIG=/etc/nginx/sites-enabled/$SDOMAIN
cp $TEMPLATE $SCONFIG
sed -i -e "s/%DOMAIN%/$SDOMAIN/g" $SCONFIG
sed -i -e "s/%SITEDIR%/$SDIR/g" $SCONFIG
mkdir $SDIR
chown john:www-data $SDIR
chmod a-rwx,u+rwx,g+rx $SDIR
if nginx -t; then
nginx -s reload
echo "nginx reloaded with new site"
fi
Running it produces the following output, and I'm not quite sure why. I really need an extra set of eyes...
sed: -e expression #1, char 14: unknown option to `s'
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
nginx reloaded with new site
In the case of %SITEDIR%, if your $SDIR contains a directory name, then the first / in the name will be seen as the end of the s/// command, rather than as data.
The bad answer is to try to pick a sigil which won't likely be in the filename -- for instance, if you don't expect the # sign to be in a filename, use:
sed -i -e "s#%SITEDIR%#$SDIR#g"
The good answer is to use a completely different tool -- awk, perl, etc. There's an awk script which does this safely in BashFAQ #21.
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.