2016-01-15 8 views
0

В последнем сценарии bash мне потребовалась функция стандартизации вызовов на сервер mysql. Моя первая версия функции была такой:Выполнение выполнения динамического запроса mysql

mysqlfunc() 
{ 
    args="-A" 
    if [ "$1" = "++" ]; then 
     shift 
     while [ 1 ]; do 
      if [ "$1" = "--" ]; then 
       shift 
       break 
      fi 
      args="$args $1" 
      shift 
     done 
    fi 

    query="-e \"$*\"" 
    if [ -f "$1" ]; then 
     query="< $1" 
    fi 

    mysql $args -h<host> -p<password> -P<port> -u<user> <database> $query 
} 

Эта версия функции создала синтаксически корректную инструкцию mysql; выполнение оцениваемой команды в командной строке без ошибок. Однако, когда файл был передан функции, такие как:

mysqlfunc $DB_Scripts/mysql_table_create.sql 

Команда MySQL потерпит неудачу, жаловалась на то, что представляется либо некорректные аргументы поставляются или неправильный синтаксис. В нем не указывалось, какая из них, только распечатала справку об использовании для mysql.

Мой вопрос: Почему это динамическое назначение присваивается?


Пример:

Вызов функции:

mysqlcmd $PATH_TO_FILE/example.sql 

команда Mysql выполнено:

mysql -A -h<host> -p<password> -P<port> -u<user> <database> < <path_to_file>/example.sql 

Результат:

Использование для mysql, напечатанного на терминале

+0

Что такое '$ args'? Вы действительно имеете в виду, что первый аргумент функции должен быть в строке '-e' ** и ** использоваться как' <$ 1'? Вы ожидаете, что какие-либо аргументы вашей функции будут содержать пробелы в них? Вы ожидаете, что это будет безопасно для произвольного ввода? Добавьте 'set -x' в начало функции и' set + x' до конца, а затем запустите его и посмотрите, какие команды фактически выполняются. –

+0

@EtanReisner $ args содержит параметры, переданные при вызове функции (например, mysqlfunc --silent "select * from TABLE"). Парсер параметров выделяет все, кроме команды sql для выполнения, поэтому да, это безопасно. Как я уже отмечал, команда отлично работает в командной строке. – Frostfyre

+0

'$ *' - это все текущие аргументы (включая '$ 1'). Это ты имел в виду? Вы назначаете аргументы в '$ args' в какой-то момент, потому что ваш фрагмент не показывает этого. Двойные кавычки в '$ query' не будут удалены оболочкой (поэтому' mysql' будет казаться ими), которая может быть не такой, какой вы хотите. Какая команда ** точно ** запустила ее, когда она не удалась, и что было ** точным ** сообщением об ошибке? –

ответ

1

Нельзя помещать метасимволы оболочки, такие как < внутри переменных, и иметь их функцию.

Это не то, как работает парсер. Оболочка не видит < в переменном результате в качестве оператора перенаправления, который видит в нем как литеральную строку.

Это часть покрытий Bash FAQ 050.

+0

Bummer. Думаю, я пытался быть слишком креативным. Моя текущая версия скрипта не использует переменную запроса и работает отлично. – Frostfyre

0

вы можете сделать что-то вроде

if [ -f "$1" ]; then 
    cat $1 | mysql $args -h<host> -p<password> -P<port> -u<user> <database> 
else 
    mysql $args -h<host> -p<password> -P<port> -u<user> <database> $query 
fi 

работ с PSQL

+0

Это в значительной степени то, что я закончил, но явно используя «<$ 1», вместо того, чтобы указывать файл. Работает отлично. – Frostfyre