Назад | Перейти на главную страницу

управлять сценарием bash с переменными из внешнего файла

Я хотел бы управлять сценарием bash следующим образом:

#!/bin/sh
USER1=_parsefromfile_
HOST1=_parsefromfile_
PW1=_parsefromfile_
USER2=_parsefromfile_
HOST2=_parsefromfile_
PW2=_parsefromfile_

imapsync \
--buffersize 8192000 --nosyncacls --subscribe --syncinternaldates --IgnoreSizeErrors \
--host1 $HOST1 --user1 $USER1 --password1 $PW1 --ssl1 --port1 993 --noauthmd5 \
--host2 $HOST2 --user2 $USER2 --password2 $PW2 --ssl2 --port2 993 --noauthmd5 --allowsizemismatch

с параметрами из контрольного файла, например:

host1 user1 password1 host2 user2 password2
anotherhost1 anotheruser1 anotherpassword1 anotherhost2 anotheruser2 anotherpassword2 

где каждая строка представляет один запуск сценария с извлеченными параметрами и преобразованными в переменные.

какой способ сделать это наиболее элегантно?

PAT

В сценариях оболочки это обычно выполняется с помощью source функция, которая выполняет файл как сценарий оболочки, как если бы он был встроен в сценарий, который вы запускаете - это означает, что любые переменные, которые вы устанавливаете в файле, экспортируются в ваш сценарий.

Обратной стороной является то, что (а) ваш файл конфигурации выполняется, поэтому это представляет угрозу безопасности, если непривилегированные пользователи могут редактировать привилегированные файлы конфигурации. И (б) синтаксис вашего файла конфигурации ограничен допустимым синтаксисом bash. Тем не менее, это ДЕЙСТВИТЕЛЬНО удобно.

config.conf

USER=joe
PASS=hello
SERVER=127.0.0.2

script.sh

#!/bin/bash

# Set defaults   
USER=`whoami`

# Load config values
source config.conf

foobar2000 --user=$USER --pass=$PASS --HOST=$HOST

source можно сократить до одного . - так что следующие два эквивалентны:

 source file.sh
 . file.sh

Что-то вроде этого. Важный бит - это использование читать чтобы захватить строку как массив.

#!/bin/bash
configfile=/pathtocontrolfile
cat $configfile | while read -a HR ; do

  [[ -z ${HR[0]} ]] && continue  # skip empty lines

  USER1=${HR[0]}
  HOST1=${HR[1]}
  PW1=${HR[2]}
  USER2=${HR[3]}
  HOST2=${HR[4]}
  PW2=${HR[5]}

  imapsync \
  --buffersize 8192000 --nosyncacls --subscribe --syncinternaldates --IgnoreSizeErrors \
  --host1 $HOST1 --user1 $USER1 --password1 $PW1 --ssl1 --port1 993 --noauthmd5 \
  --host2 $HOST2 --user2 $USER2 --password2 $PW2 --ssl2 --port2 993 --noauthmd5 --allowsizemismatch

done

Я думаю, вам следует использовать что-то вроде getopts, если вы хотите сделать свой сценарий интеллектуальным, вместо того, чтобы просто пытаться читать ваши аргументы на основе чисел.

Что-то вроде этого.

#!/bin/bash

while getopts ":a" opt; do
  case $opt in
    a)
      echo "-a was triggered!" >&2
      ;;
    \?)
      echo "Invalid option: -$OPTARG" >&2
      ;;
  esac
done


$ ./go_test.sh -a
-a was triggered!
$ 

Вы также можете разбирать аргументы. Вы можете прочитать более подробную информацию об учебнике на Вот.

Я нашел здесь рабочее решение: https://af-design.com/2009/07/07/loading-data-into-bash-variables/

if [ -f "$SETTINGS_FILE" ];then
    . "$SETTINGS_FILE"
fi