Multiple line text save to file with Makefile - makefile

I want to save multiple line text to a file with GNU Make(Makefile). But it give me error. I want to make a virtual host configuration file with this script. $$dir will be the name given by user.Help me,plz.
define info =
echo <VirtualHost *:80>
echo ServerAdmin webmaster#localhost
echo ServerName $$dir.io
echo ServerAlias www.$$dir.io
echo DocumentRoot /var/www/$$dir/public_html
echo <Directory /var/www/$$dir/public_html/>
echo Options Indexes FollowSymLinks MultiViews
echo AllowOverride All
echo Order allow,deny
echo allow from all
echo </Directory>
echo </VirtualHost>
endef
echo $$info > /etc/apache2/sites-avaliable/$$dir.; \
echo "Done"

This example is so broken it makes me wonder if you even tried to make this work, or if you just typed a "best guess" directly into a StackOverflow question.
info = \
echo '<VirtualHost *:80>'; \
echo ' ServerAdmin webmaster#localhost'; \
echo ' ServerName $$dir.io'; \
echo ' ServerAlias www.$$dir.io'; \
echo ' DocumentRoot /var/www/$$dir/public_html'; \
echo ' <Directory /var/www/$$dir/public_html/>'; \
echo ' Options Indexes FollowSymLinks MultiViews'; \
echo ' AllowOverride All'; \
echo ' Order allow,deny'; \
echo ' allow from all'; \
echo ' </Directory>'; \
echo '</VirtualHost>';
all:
( $(info) ) > /etc/apache2/sites-avaliable/$(dir); \
echo "Done"
You don't specify exactly what "given by the user" means (on the make command line? In the environment? elsewhere in the makefile?).

Related

Running cql statements with shell script

I have a below shell script which reads a file and updates the table. But the problem with the below code is that a connection is established for running each sql statements. I am looking for recommendation to enhance this code.
#!/bin/bash
input="/Users/temp/newfile.txt"
while IFS= read -r var
do
echo "update keyspace.tableName set randomColumn='randomText' where random_id='$var'; exit" | ./cqlsh serverName -u username -p password
if [ $? -eq 0 ]; then
echo SUCCESS
echo "select random_id,randomColumn from keyspace.tableName where random_id='$var'; exit" | ./cqlsh serverName -u username -p password
else
echo FAIL
fi
done < "$input"
I suggest doing this with the Python driver if you'd like better performance.
This example should be roughly equivalent:
#! /usr/bin/env python3
from cassandra.cluster import Cluster
from cassandra.auth import PlainTextAuthProvider
cluster = Cluster(auth_provider=PlainTextAuthProvider(username='cassandra', password='cassandra'))
session = cluster.connect()
with open("/Users/temp/newfile.txt") as f:
for line in f:
try:
rows = session.execute("UPDATE keyspace.tableName SET randomColumn='randomText' WHERE random_id=%(var)s", {'var'=line})
print("SUCCESS")
for r in rows:
print(r)
except Exception:
print("FAIL")
edit: you can even go a step further and use prepared statements and async queries, which will provide very significant performance increases if you are making a large volume of queries.
cqlsh has a -f option which allows to run cql statement from a file. You could generate the cql statements by parsing your newfile.txt and then run cqlsh with -f option
At the very basic level, you could do something like this:
#!/bin/bash
input="newfile.txt"
while IFS= read -r var
do
echo "update ks.t1 set name='randomText' where id=$var;" >> result
done < "$input"
./cqlsh serverName -u username -p password -f result
if [ $? -eq 0 ]; then
echo SUCCESS
echo "select * from keyspace.tableName; exit" | ./cqlsh serverName -u username -p password
else
echo FAIL
fi
I suggest to use cqlsh -e with xargs :
#!/bin/bash
input="/Users/temp/newfile.txt"
while IFS= read -r var
do
echo "update keyspace.tableName set randomColumn='randomText' where random_id='$var';" | xargs cqlsh serverName -u 'username' -p 'password' -e
if [ $? -eq 0 ]; then
echo SUCCESS
echo "select random_id,randomColumn from keyspace.tableName where random_id='$var';" | xargs cqlsh serverName -u 'username' -p 'password' -e
else
echo FAIL
fi
done < "$input"

Send e-mail using command line and save IP rules

I am coding a script to select some IPs from a table in a DB, and then use IPTables rules to ban theses IPs, last step is to notify by e-mail, but I am getting 2 errors:
#!/bin/bash
Now=$(date +"%d-%m-%Y %T")
fileLocation="/var/lib/mysql/DBName/"
fileName="ip2ban.txt"
filePath=$fileLocation$fileName
curLocation=$(pwd)
#Connect to DB and select ban_ip
mysql -u root -pPASSWORD -D DBName -e 'SELECT ip INTO OUTFILE "'$filePath'" FROM ban_ip WHERE ip_tables = "0"' >> banIP.log 2>&1
selRes=$?
# If the command was successful
if [ $selRes -eq "0" ]
then
# We need to check if the file exists on the saved location
#find $fileLocation -type f -iname "ip2ban.txt" -empty => To check if file empty or not
if [ -f $filePath ]
then
mv $filePath $curLocation'/ip2ban.txt'
# Connect to DB and update the ban_ip
mysql -u root -pPASSWORD -D DBName -e 'UPDATE ban_ip SET ip_tables = "1" WHERE ip_tables = "0"' >> banIP.log 2>&1
upRes=$?
if [ $upRes -eq "0" ]
then
# Send message for succesful result
echo -e "Database updated with new banned IPs on $Now \nThank you for using this script" 2>&1 | sed '1!b;s/^/To: myID#gmail.com\nSubject: New banned IPs[Success]\n\n/' | sendmail -t
else
# Send message for failure result
echo -e "We cannot update the ban_ip table on $Now \nThank you for using this script" 2>&1 | sed '1!b;s/^/To: myID#gmail.com\nSubject: [Failure] New banned IPs\n\n/' | sendmail -t
fi
fi
else
echo 'Something wrong with Select statment on' $Now >> banIP.log
fi
# Save IPTables rules
iptables-save > /root/Scripts/IPTables/BannedIPs.conf // LIGNE 53
I am getting 2 errors:
line 53: iptables-save: command not found
line 37: sendmail: command not found
However the sendamil is already installed, with mail, postfix:
# which sendmail
/usr/sbin/sendmail
# which mail
/usr/bin/mail
# which postfix
/usr/sbin/postfix
Thanks for your usual support
According to the crontab(5) man page for Linux:
PATH is set to "/usr/bin:/bin".
Meaning your shell script will not be able to find anything under /usr/sbin or /sbin. Change this with by adding the following near the top of your script:
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
Also the environment can be set from within the crontab. See https://stackoverflow.com/a/14694543/5766144 for how to do this.

Split a string in gnu make with a separator

I have makefile with below code:
.PHONY: $(PROJECTDIR)/projectroot
$(PROJECTDIR)/projectroot:
if [ -f $(#)/etc/release ]; then \
#$(RELEASE_VERSION) will have value something like 00.01.02.03
IFS=. read major minor micro build <<<"${RELEASE_VERSION}" \
echo major=${major} > $(#)/etc/release \
echo major=${minor} >> $(#)/etc/release; \
echo major=${micro} >> $(#)/etc/release; \
echo major=${build} >> $(#)/etc/release; \
fi
I am expecting the $(#)/etc/release to get content like below:
major=00
minor=01
micro=02
build=03
I need to replace IFS=. with some equivalent command in gnu make, can you please help me with this? thanks.
The problem is that you're readin the values into shell variables called major, minor etc. but then you are printing Make variables with the same names. The shell cannot set the Make variables.
To fix your existing code you need to repeat the $ characters as $$ so Make outputs a $ to the shell, which will interpret them (also you're saying "major" every time, and are missing some semi-colons):
IFS=. read major minor micro build <<<"${RELEASE_VERSION}" ; \
echo major=$${major} > $(#)/etc/release ;\
echo minor=$${minor} >> $(#)/etc/release; \
echo micro=$${micro} >> $(#)/etc/release; \
echo build=$${build} >> $(#)/etc/release; \
But to do it within make you can use the subst and word functions:
REL_WORDS := $(subst ., ,${RELEASE_VERSION})
...
echo major=$(word 1,${REL_WORDS}) > $(#)/etc/release ;\
echo minor=$(word 2,${REL_WORDS}) >> $(#)/etc/release ;\
echo micro=$(word 3,${REL_WORDS}) >> $(#)/etc/release ;\
echo build=$(word 4,${REL_WORDS}) >> $(#)/etc/release ;\
.PHONY: $(PROJECTDIR)/projectroot
$(PROJECTDIR)/projectroot: $(PROJECTDIR)/projectroot/etc/release
$(PROJECTDIR)/projectroot/etc/release:
echo "${RELEASE_VERSION}" | \
sed 's/^/major=/; s/\./\nminor=/; s/\./\nmicro=/; s/\./\nbuild=/' >$#
Add dependencies to the release file.

Dynamic dialog --menu box in bash

I'm searching for good explanation about making dynamic dialog --menu box in bash. I'm trying to load a list of users from a file that have structure like this:
------ user ------
/rw412 0.2 /rx511 23.1 /sgo23 9.2
/fs352 1.4 /...
------ another_user ------
/rw412 0.3 / and so on...
of course the user name is between ------
i don't really know how to use loops inside dialog. I'm also trying to avoid creating additional files.
Please help
Here's an example of one way to use dialog. The options array can be built up in a variety of ways (see below).
#!/bin/bash
cmd=(dialog --keep-tite --menu "Select options:" 22 76 16)
options=(1 "Option 1"
2 "Option 2"
3 "Option 3"
4 "Option 4")
choices=$("${cmd[#]}" "${options[#]}" 2>&1 >/dev/tty)
for choice in $choices
do
case $choice in
1)
echo "First Option"
;;
2)
echo "Second Option"
;;
3)
echo "Third Option"
;;
4)
echo "Fourth Option"
;;
esac
done
Here's one way to build the options array:
count=0
while read -r dashes1 username dashes2
do
if [[ $dashes1 == --*-- && $dashes2 == --*-- ]]
then
options+=($((++count)) "$username")
fi
done < inputfile
following the above clues and having my own ideas as well; here is another way:
#!/bin/bash
MENU_OPTIONS=
COUNT=0
for i in `ls`
do
COUNT=$[COUNT+1]
MENU_OPTIONS="${MENU_OPTIONS} ${COUNT} $i off "
done
cmd=(dialog --separate-output --checklist "Select options:" 22 76 16)
options=(${MENU_OPTIONS})
choices=$("${cmd[#]}" "${options[#]}" 2>&1 >/dev/tty)
for choice in $choices
do
" WHATEVER from HERE"
done
Ok
Following Dennis Williamson clues and my own ideas i came to something like this
#!/bin/bash
c=0
while read -r dashes1 username dashes2
do
if [[ $dashes1 == --*-- && $dashes2 == --*-- ]]
then
options=("${options[#]}" "$((++c))" "$username")
fi
done < inputfile
cmd=(dialog --backtitle "title" --menu "Select_user:" 22 38 2) #2 becouse
i know there will be 2 options
command=`echo "${cmd[#]}" "${options[#]}" "2>file"`
$command
Now, there is an error like this:
Error: Expected 2 arguments, found only 1.
Why is that??
This is a repost of my answer from a very similar question. I arrived at this answer with the help of a cohort but couldn't find it in the wild; I think adding it here might help others.
The ${options[#]} array required the following (rather strange) structure in order to work. This was tested on bash in Ubuntu 18.04:
#Dynamic dialogs require an array that has a staggered structure
#array[1]=1
#array[2]=First_Menu_Option
#array[3]=2
#array[4]=Second_Menu_Option
Here is bash code that reads in a directory listing from an argument and creates a dynamic menu from it:
#! /bin/bash
#usage: Dynamic_Menu.bash /home/user/target_directory
declare -a array
i=1 #Index counter for adding to array
j=1 #Option menu value generator
while read line
do
array[ $i ]=$j
(( j++ ))
array[ ($i + 1) ]=$line
(( i=($i+2) ))
done < <(find $1 -type f) #consume file path provided as argument
#Define parameters for menu
TERMINAL=$(tty) #Gather current terminal session for appropriate redirection
HEIGHT=20
WIDTH=76
CHOICE_HEIGHT=16
BACKTITLE="Back_Title"
TITLE="Dynamic Dialog"
MENU="Choose a file:"
#Build the menu with variables & dynamic content
CHOICE=$(dialog --clear \
--backtitle "$BACKTITLE" \
--title "$TITLE" \
--menu "$MENU" \
$HEIGHT $WIDTH $CHOICE_HEIGHT \
"${array[#]}" \
2>&1 >$TERMINAL)

shell script + constant spaces between the IP to the aliases name

from my ksh script
.
echo $IP1 $ALIAS1 >> /etc/hosts
echo $IP2 $ALAIS2 >> /etc/hosts
echo $IP3 $ALIAS3 >> /etc/hosts
I get the hosts file as the following
10.10.10.10 node1_star
10.10.10.100 node_from_some_where
10.10.1.1 Node_HP_MACHINE
what the simple way to create the following hosts file view
in order to get constant spaces between the IP to the aliases name
as the follwoing:
(it could be by printf or by echo manipulation)
10.10.10.10 node1_star
10.10.10.100 node_from_some_where
10.10.1.1 Node_HP_MACHINE
printf is a powerful function that can do exactely what you want.
printf "%-20s %s\n" "$IP1" "$ALIAS1" >> /etc/hosts

Resources