Есть несколько скриптов, что-то делающих при поднятии/опускании интерфейсов. Думал по-быстрому собрать некий мастер-конфиг, при изменении параметров просто вписывать в его переменные и генерировать по образцам новые скрипты с нужными переменными.
Пример.
Файл с переменными для всего и циклом для генерации нового из имеющихся "идеальных"
master_with_variables.sh
WANIF_MASTER_VAR=eth0
WANIF_IP_MASTER_VAR=172.10.23.11
SOME_EXTERNAL_RES_MASTER_VAR=ya.ru
cat ./ideal_cfg_to_generate.sh | \
while read STR
do
eval eval 'echo $STR'
done >> ./new_generated_file.sh
ideal_cfg_to_generate.sh
WANIF=$WANIF_MASTER_VAR
WANIF_IP=$WANIF_IP_MASTER_VAR
IP_EXTERN_RESOURCE=$(nslookup $SOME_EXTERNAL_RES_MASTER_VAR | tail -n 2 | awk '{print $2}')
Сгенерированый файл
new_generated_file.sh
WANIF=eth0
WANIF_IP=172.10.23.11
IP_EXTERN_RESOURCE=87.250.250.242
#вместо ожидаемого IP_EXTERN_RESOURCE=$(nslookup
ya.ru | tail -n 2 | awk '{print $2}')
Как-то запретить eval выполнять команды $(...) можно? Или только в "мастер-скрипте" все переменные со значениями пихать в массив, при получении строки -- проверять, что из переменных там вызывается и подменять тем же sed на имеющееся в массиве значение?
Решено с помощью valrust в следующих сообщениях.
АП. На случайных скриптах работает кривовато, где-то eval как-то всё же срабатывает. Попробую через HERE DOCUMENTS, может получится обработке пачки файлов приписать.
UP1. С ручной подстановкой через grep-sed вроде сносно отрабатывает.
В одной со скриптом папе создать master_cfg, складывать туда скрипты-образцы с воссозданием структуры ФС внутри папки, с запросом вызова значения переменной вместо фиксированного значения (например вместо address=192.168.0.1 -- address=$ADDRESS_FROM_MASTER_SCRIPT).
В мастер-скрипте в массиве указать переменные и их значения, которые будут подменяться в скриптах-образцах, например ADDRESS_FROM_MASTER_SCRIPT=192.168.0.1
В директории со скриптом же будет создан temp_cfg, все изменения будут производиться уже в ней.
Основной файл текстом здесь и текстом во вложении (переименовать txt в sh)
#!/bin/bash
#Description
#Script then subsitutes variables from ARRAY_WITH_VARS
#in files, given in master_cfg dir
#Before work it's copy master_cfg to temp_cfg dir
#and makes all changes in temp_cfg directory
#binaries needed
#bash awk sed file
#config dirs, without last /
MASTERCFG_DIR=master_cfg
TEMPCFG_DIR=temp_cfg
GENERATEDCFG_DIR=generated_cfg
#in DEBUG=yes enables messages with echo_debug function
DEBUG=yes
#make files and folders for work
SCRIPTNAME=$(basename $0)
SCRIPTDIR=$(echo $0 | sed "s/$SCRIPTNAME//")
WORKDIR="$SCRIPTDIR"
cd $WORKDIR
mkdir $TEMPCFG_DIR $GENERATEDCFG_DIR
cp -R -p $MASTERCFG_DIR/* $TEMPCFG_DIR
#add variables as elements of array.
#if you need to use variables as is,
#uncomment line "eval ${ARRAY_WITH_VARS[@]}"
#or use SUBSTITUTE_VARIABLES_IN_STRING_WITH_EVAL
declare -a ARRAY_WITH_VARS
ARRAY_WITH_VARS=( \
IF_WAN_YARNET_MASTER=enp5s2 \
IF_WAN_IP_YARNET_MASTER=10.200.24.231/24 \
IF_WAN_SUBNETMASK_YARNET_MASTER=255.255.255.0 \
IF_PPP_MASTER=ppp0 \
IF_LAN_MASTER=enp6s0 \
IF_LAN_IP_MASTER=192.168.0.10/27 \
IF_LAN_IP_SUBNET_MASK=255.255.255.224 \
IF_LAN_IP_SUBNET_MASK_SHORT=27 \
IF_WAN2VIRT_BEELINE_MASTER=eth8 \
#Добавить маршруты до выданных подсетей через выданные адреса в подсети 192.168.0.0/27
#Добавить nat от каждого из выданных хостов, nat для всей выданной подсети.
LAN_CLIENT_1=192.168.0.30/27 \
LAN_CLIENT_1_SUBNET=192.168.0.32/27 \
LAN_CLIENT_2=192.168.0.29/27 \
LAN_CLIENT_2_SUBNET=192.168.0.64/27 \
LAN_CLIENT_3=192.168.0.28/27 \
LAN_CLIENT_3_SUBNET=192.168.0.96/27 \
PATH_TO_FILE=/long/path/to/file
VARIABLE_WITH_SPACES="variable with spaces"
)
#if you need variables from array as variables, execute next string
#eval ${ARRAY_WITH_VARS[@]}
#internal script vars
#stay it empty
VAR=
SUBVAR=
#script run structure
#using variables, then set in beginning
#cd to workdir, copy master_cft to temp_cfg (or other folders if set on vars)
#call GENERATE_SEARCH_1ST_STRING_GREP one time
#call GENERATE_SCRIPTS_IN_TEMPCFG_DIR_DIRECTLY
#then calls l SUBSTITUTE_VARIABLE_IN_FILE_MANUALLY
# l GENERATE_SUBSTR_FOR_SED
echo_debug()
{
#DESC: simple proc to drop DEBUG messages
#DESC: if DEBUG variable, installed in is working proc, is no, then do nothing, else echo all arguments.
#BINS:
#VARS: PROCNAME
#GLOBAL VARS: CURRDIR, TEMPODIR
#PROCS:
local PROCNAME=echo_debug
#run
if [[ $DEBUG == yes ]];
then echo $@
fi
}
SUBSTITUTE_VARIABLES_IN_STRING()
{
#path with eval does not works
#Dropped unused function
cat "$1" | \
while read VAR
do
if [[ "$VAR" =~ ^#.* ]]
then
echo $VAR
else
if [[ "$VAR" =~ \$ ]]
then
SUBVAR="echo $VAR"
#make double substitutuon
eval eval '$SUBVAR'
else
echo $VAR
fi
fi
done
}
GENERATE_SCRIPTS_FROM_TEMP_LINE_BY_LINE_TO_GENERATED_PROC()
{
#generating substituted scripts line-by-line
#from TEMPCFG_DIR to GENERATEDCFG_DIR
#makes substitution with SUBSTITUTE_VARIABLES_IN_STRING function
#droppet, does not used
for i in $(find ./$TEMPCFG_DIR -type f )
do
FILENAME=$(echo $i | awk -v FS="/" '{ print $NF }')
echo_debug Filename is $FILENAME
FILEPATH=$(echo $i | sed "s/$FILENAME//")
echo_debug filepath is $FILEPATH
#add backslash to $ and " \" in begin of each line
#in any file on $TEMPCFG_DIR
#needed for eval eval "echo $VAR" string
sed 's/\$/\\$/g; s/^/ \\/g' -i "$i"
#make dirtree in GENERATEDCFG_DIR, then equal TEMPCFG_DIR
FILEPATH_GENERATED=$(echo $FILEPATH | sed "s/$TEMPCFG_DIR/$GENERATEDCFG_DIR/")
echo fielath_generated is $FILEPATH_GENERATED
#mkdir -p $FILEPATH_GENERATED
SUBSTITUTE_VARIABLES_IN_STRING "$i" > "$FILEPATH_GENERATED$FILENAME"
done
}
GENERATE_SCRIPTS_IN_TEMPCFG_DIR_DIRECTLY()
{
#makes substitution in TEMPCFG_DIR
#with SUBSTITUTE_VARIABLE_IN_FILE_MANUALLY
for i in $(find ./$TEMPCFG_DIR -type f )
do
#FILENAME=$(echo $i | awk -v FS="/" '{ print $NF }')
#echo_debug Filename is $FILENAME
#FILEPATH=$(echo $i | sed "s/$FILENAME//")
#echo_debug filepath is $FILEPATH
SUBSTITUTE_VARIABLE_IN_FILE_MANUALLY "$i"
done
}
WRITE_GENERATED_TO_ROOT_PROC()
{
#write generated files from GENERATEDCFG_DIR to /
for i in $(find ./$GENERATEDCFG_DIR -type f )
do
FILENAME=$(echo $i | awk -v FS="/" '{ print $NF }')
echo Filename is $FILENAME
FILEPATH=$(echo $i | sed "s/$FILENAME//")
echo filepath is $FILEPATH
#delete GENERATEDCFG_DIR part from FILEPATH
#it's will be obsolette target path for copy to
FINALPATH=$(echo $FILEPATH | sed "s/\.\/$GENERATEDCFG_DIR//")
echo finalpath is $FINALPATH
echo mkdir -p $FINALPATH
echo "cat $i > $FINALPATH$FILENAME"
done
}
GENERATE_SEARCH_1ST_STRING_GREP()
{
#will return variable SEARCH_1ST_STR_GREP
#it's works with unchangable data,
#so it can run without a cycle before other functions
#needed variables
#ARRAY_WITH_VARS
#drop SEARCH_1ST_STR_GREP
SEARCH_1ST_STR_GREP=
COUNT_VAR=0
for i in $(seq 0 ${#ARRAY_WITH_VARS[@]})
do
VAR_NAME_CURRENT=$(echo ${ARRAY_WITH_VARS[$i]} | awk -v FS="=" '{print $1}')
echo_debug $VAR_NAME_CURRENT
COUNT_VAR=$(( $COUNT_VAR + 1 ))
SEARCH_1ST_STR_GREP=" $SEARCH_1ST_STR_GREP $VAR_NAME_CURRENT"
done
#change " " to " \\\$", " " to "\|" before name of variable
#we will search with grep -E $EXPR1 or $EXPR2 of $EXPRN. $ is symbol too
#like grep -E \$EXPR1\|\$EXPR2
SEARCH_1ST_STR_GREP="$(echo $SEARCH_1ST_STR_GREP | sed 's/^/ /; s/ / \\\$/g; s/^ //; s/ /\|/g')"
}
GENERATE_SUBSTR_FOR_SED()
{
#variables needed
#SEARCH_GREP_RETURN, SEARCH_GREP_RETURN_CUTED
#generating sed programms for substitute
#variables found by grep
#drop variable value before work
SUBST_STR_FOR_SED=
#Make links with found variables names and their position in array
#get their values
for i in $(echo $SEARCH_GREP_RETURN)
do
for a in $(seq 0 ${#ARRAY_WITH_VARS[@]})
do
VAR_NAME_IN_ARRAY=$(echo $i | sed 's/\$//g')
if [[ $(echo ${ARRAY_WITH_VARS[$a]} | awk -v FS="=" '{print $1}') == "$VAR_NAME_IN_ARRAY" ]];
then
VAR_NUMBER_IN_ARRAY=$a
VAR_NUMBERED_IN_ARRAY_VAL=$(echo ${ARRAY_WITH_VARS[$a]} | awk -v FS="=" '{print $2}')
#add backslashes for every symbol to send in for sed
VAR_NUMBERED_IN_ARRAY_VAL=$(echo $VAR_NUMBERED_IN_ARRAY_VAL | sed '!s/[A-Za-z0-9]/\\&/g; s/\//\\\//g; s/ /\ /g')
echo_debug $i has number $a \in ARRAY_WITH_VARS
TEMPVAR="s/\\$i/$VAR_NUMBERED_IN_ARRAY_VAL/g;"
echo_debug current substitute rule \for \sed is $TEMPVAR
SUBSTR_FOR_SED="$SUBSTR_FOR_SED $TEMPVAR "
#drop TEMPVAR
TEMPVAR=
break
fi
done
done
}
SUBSTITUTE_VARIABLE_IN_STRING_MANUALLY()
{
#returns substituted string, then given as argument
#before start it you need execute GENERATE_SEARCH_1ST_STR_GREP separetely
#on uncomment call of that function here
#GENERATE_SEARCH_1ST_STR_GREP
echo
#echo all arguments after function and find something from generated search string
echo_debug Search string is $SEARCH_1ST_STR_GREP
echo_debug COUNT_VAR is $COUNT_VAR
echo_debug Given argument\(s\) $@
echo_debug Comparing Given argument with search string
SEARCH_GREP_RETURN=$(echo $@ | grep -E -oh "$SEARCH_1ST_STR_GREP")
if [[ -z "$SEARCH_GREP_RETURN" ]]
then
echo_debug No patterns to substitute found, skipping
return
fi
SEARCH_GREP_RETURN_CUTED=$(echo $SEARCH_GREP_RETURN | sed 's/\$//g')
echo_debug ARGS found \in given string $(echo $@ | grep -E -oh $SEARCH_1ST_STR_GREP)
echo_debug
GENERATE_SUBSTR_FOR_SED
echo $@ | sed "$SUBSTR_FOR_SED"
#drop substitution string for sed
SUBST_STR_FOR_SED=
SEARCH_1ST_STR_GREP=
SEARCH_GREP_RETURN_CUTED=
}
SUBSTITUTE_VARIABLE_IN_FILE_MANUALLY()
{
#Working with text file given as argument
#generate search string for grep
#from names of variables and $ before them
#" " is important to change " NAME" to " $NAME"
if [[ $( file --mime-type "$1" | grep -c -i text ) -gt 0 ]]
then
echo_debug 'its text file, working'
else
echo_debug 'its not text file, skipping'
return
fi
#before start it you need execute GENERATE_SEARCH_1ST_STR_GREP separetely
#on uncomment call of that function here
#GENERATE_SEARCH_1ST_STR_GREP
#check patterns in file, generate SEARCH_GREP_RETURN
#echo all arguments after function and find something from generated search string
echo_debug Search string is $SEARCH_1ST_STR_GREP
echo_debug COUNT_VAR is $COUNT_VAR
echo_debug Given argument $1
echo_debug Comparing Given argument with search string
SEARCH_GREP_RETURN=$(grep -E -oh "$SEARCH_1ST_STR_GREP" $1)
if [[ -z "$SEARCH_GREP_RETURN" ]]
then
echo_debug No patterns to substitute found, skipping
return
else
echo_debug Patterns found, working
fi
SEARCH_GREP_RETURN_CUTED=$(echo $SEARCH_GREP_RETURN | sed 's/\$//g')
echo_debug ARGS found \in given \file $SEARCH_GREP_RETURN
echo_debug
GENERATE_SUBSTR_FOR_SED
#using sed to make substitution in file directly
echo_debug "command to change file is"
echo_debug "sed "$SUBSTR_FOR_SED" -i "$1""
sed "$SUBSTR_FOR_SED" -i "$1"
}
#commented test run strings
#used for testing funtions separately
#GENERATE_SCRIPTS_FROM_TEMP_LINE_BY_LINE_TO_GENERATED_PROC
#WRITE_GENERATED_TO_ROOT_PROC
#echo ${ARRAY_WITH_VARS[@]}
#echo var IF_WAN_YARNET_MASTER is $IF_WAN_YARNET_MASTER
#echo 'original string is klklk$IF_WAN_YARNET_MASTERlklklk\$IF_PPP_MASTERlk klk klgh $PATH_TO_FILE asas$VARIABLE_WITH_SPACES'
#echo 'Substituted string is...'
#SUBSTITUTE_VARIABLE_IN_STRING_MANUALLY $(echo 'klklk$IF_WAN_YARNET_MASTERlklklk\$IF_PPP_MASTERlk klk klgh $PATH_TO_FILE asas$VARIABLE_WITH_SPACES')
#GENERATE_SEARCH_1ST_STRING_GREP
#SUBSTITUTE_VARIABLE_IN_FILE_MANUALLY "/home/dark-archangel/Documents/scripts/net_router/config/temp_cfg/etc/network/interfaces"
GENERATE_SEARCH_1ST_STRING_GREP
GENERATE_SCRIPTS_IN_TEMPCFG_DIR_DIRECTLY
Как основной скрипт работает, что вызывает
#script run structure
#using variables, then set in beginning
#cd to workdir, copy master_cft to temp_cfg (or other folders if set on vars)
#call GENERATE_SEARCH_1ST_STRING_GREP one time
#call GENERATE_SCRIPTS_IN_TEMPCFG_DIR_DIRECTLY
#then calls l SUBSTITUTE_VARIABLE_IN_FILE_MANUALLY
# l GENERATE_SUBSTR_FOR_SED
---
Строки для поисковика
bash eval eval, bash double substitution, bash evaluate, eval экранировать, eval экранирование, Here documents, EOF, generate config, generate config files, script, bash script, bash scripting. подстановка значения переменной, bash substitute variables via sed, bash substitution sed grep, bash manual variable substitution, config generation, cfg generation, config cfg generator generation create