команда `read` не работает в Makefile

У меня есть скрипт make для выполнения 3 задач:

  1. Импортировать базу данных MySQL
  2. Переместить файл конфигурации
  3. Настроить конфигурационный файл

Для этих задач сценарий требует 3 ввода:

  1. MySQL Host
  2. Имя пользователя MySQL
  3. Пароль MySQL

По какой-то причине всякий раз, когда я read ввод, он сохраняет правильную переменную, но содержимое – это имя переменной, которое я сохраняю без первой буквы. Я не могу понять, почему это так.

Вот Makefile :

 SHELL := /bin/bash default: @echo "Welcome!";\ echo -n "Please enter the MySQL host (default: localhost):";\ read host;\ host=${host:-localhost};\ echo -n "Please enter the MySQL username:";\ read username;\ echo -n "Please enter the MySQL password:";\ read -s password;\ mv includes/config.php.example includes/config.php 2>/dev/null;true;\ sed 's/"USER", ""/"USER", "$(username)"/g' includes/config.php > includes/config.php;\ sed 's/"PASSWORD", ""/"PASSWORD", "$(password)"/g' includes/config.php > includes/conf$ echo $username;\ echo $password;\ mysql -u "$username" -p"$password" codeday-team < ./codeday-team.sql;\ echo "Configuration complete. For further configuration options, check the config file$ exit 0; 

Выход:

 Welcome! Please enter the MySQL host (default: localhost): Please enter the MySQL username:<snip> Please enter the MySQL password:sername assword ERROR 1045 (28000): Access denied for user 'sername'@'localhost' (using password: YES) Configuration complete. For further configuration options, check the config file includes/config.php 

Как вы можете видеть, он выводит sername и assword . Для жизни меня я не могу это исправить!

Хотя цель этого сообщения – решить проблему read , я был бы признателен за любые советы, отчеты об ошибках или предложения. Я могу присудить им награду.

Спасибо за помощь!

2 Solutions collect form web for “команда `read` не работает в Makefile”

Вы смешиваете оболочку и make переменные там. Оба make и оболочка используют $ для своих переменных.

В Makefile переменными являются $(var) или $v для однобуквенных переменных и $var или ${var} в оболочках.

Но если вы напишете $var в Makefile, make поймет его как $(v)ar . Если вы хотите передать литерал $ в оболочку, вам нужно ввести его как $$ , как в $$var или $${var} чтобы он стал $var или ${var} для оболочки.

Кроме того, make run sh , а не bash для интерпретации этого кода ( Edit , sorry пропустил ваш SHELL := /bin/bash выше, обратите внимание, что во многих системах нет bash в /bin если у них вообще есть bash и := is GNU ), поэтому вам нужно использовать синтаксис sh . echo -n , read -s – синтаксис zsh / bash , а не синтаксис sh .

Лучше всего было бы добавить скрипт zsh / bash для этого (и добавить зависимость сборки от bash ). Что-то вроде:

 #! /usr/bin/env bash printf 'Welcome\nPlease enter the MySQL host (default: localhost): ' read host || exit host=${host:-localhost} printf "Please enter the MySQL username: " read username || exit printf "Please enter the MySQL password:" IFS= read -rs password || exit printf '\n' mv includes/config.php.example includes/config.php 2>/dev/null repl=${password//\\/\\\\} repl=${repl//&/\\&} repl=${repl//:/\\:} { rm includes/config.php && sed 's/"USER", ""/"USER", "'"$username"'"/g s:"PASSWORD", "":"PASSWORD", "'"$repl"'"/g' > includes/config.php } < includes/config.php || exit mysql -u "$username" -p"$password" codeday-team < ./codeday-team.sql || exit echo "Configuration complete. For further configuration options, check the config file" 

В нем рассматриваются еще несколько вопросов:

  • вам нужно -r при чтении пароля, если вы хотите разрешить пользователю использовать обратную косую черту в своем пароле.
  • вам нужно IFS= если вы хотите разрешить пользователю вводить пароль, который начинается или заканчивается пробелами
  • то же самое относится и к имени пользователя, но здесь мы делаем предположение, что пользователь не будет использовать что-либо глупое для имени пользователя, а обработка пустой дескрипции и обратной косой черты может рассматриваться как / feature /.
  • ваш ;true после того, как mv не делает то, что вы думаете, что он делает. Он не отменяет эффект параметра errexit (для make реализации, вызывающего оболочку с -e ). Вместо этого вам понадобится ||true . Здесь мы не используем errexit но делаем ошибку, обрабатывая себя с || exit || exit туда, где это необходимо.
  • Вам нужно избегать обратной косой черты, & и s:pattern:repl: separator (здесь s:pattern:repl: или он не будет работать (и может иметь неприятные побочные эффекты).
  • Вы не можете сделать sed ... < file > file , так как file будет усечен до того, как sed будет запущен. Некоторые реализации sed поддерживают опцию -i или -i '' . В качестве альтернативы вы можете использовать perl -pi . Здесь мы делаем эквивалент perl -pi вручную (удаляем и воссоздаем входной файл после того, как он открыт для чтения), но не заботясь о метаданных файла.

    Здесь было бы лучше использовать пример один как входной, а последний – как вывод.

Он по-прежнему не затрагивает еще несколько вопросов:

  • новый config.php создается с разрешениями, полученными из текущего umask который, вероятно, будет umask для чтения в мире и принадлежит пользователю, выполняющему make . Возможно, вам придется адаптировать umask и / или изменить право собственности, если includes dir не ограничивается иначе, поскольку этот файл содержит конфиденциальную информацию.
  • если пароль содержит " символы», которые, вероятно, будут ломаться (на этот раз для php ). Вы хотите либо запретить их (возвращая ошибку), либо добавить для них еще один уровень экранирования в правильном синтаксисе для этого php файла. вероятно, будут иметь схожие проблемы с обратным слэшем, и вы можете также исключить не-ascii или контрольные символы.
  • Передача пароля в командной строке mysql – это, как правило, плохая идея, так как это означает, что она выводится на выходе ps -f . Лучше использовать:

      mysql --defaults-file=<( printf '[client]\nuser=%s\npassword="%s"\n' "$username" "$password") ... 

    printf будет встроен, он не будет отображаться в выпуске ps .

  • переменная $host не используется.

  • запрос такого пользователя означает, что ваш скрипт не может быть легко автоматизирован. Вместо этого вы можете ввести данные из аргументов или (лучше для пароля) с переменными окружения.

вы не используете никаких функций Makefile, пытаетесь ли вы писать эти строки в одной оболочке?

следующий в Makefile, который вы используете

  echo $username;\ echo $password;\ 

make будет анализировать $username как $u (пустая переменная) + sername (строка)

попробуйте заменить $username на $$username если вы хотите остаться в Makefile.

  • Использование «$ {a: -b}» для назначения переменных в скриптах
  • перечислить файлы и сохранить их в переменных
  • Как использовать тройник для захвата STDOUT из кодового блока в имя файла, определенное в блоке?
  • Столкновение видимых переменных переменных
  • Shell: как использовать 2 переменные с условием
  • Запустите команду, сохраненную в переменной, чтобы эхо в файл
  • Невозможно назначить вывод вложенных команд переменной в bash
  • Как использовать расширенное значение переменной оболочки в имени другой переменной?
  • Расширение «$ @» для пользовательских переменных
  • Используйте sed для извлечения переменной из 1 файла и поместите ее в другую
  • Разделить команду и аргументы и вставить в переменную в сценарий bash
  • Interesting Posts

    Как работают службы в Debian и как я могу ими управлять?

    сортировать, но держать строку заголовка вверху

    Скопировать массив из нескольких файлов с расширением globbed, в bash 3.2

    Как заставить сервер X создавать определенные ключи и состояние?

    ОШИБКА: Нет места на ep ring

    Как получать почту при удалении файла?

    Ccache попадает только один раз во время сборки ядра

    Маршрут SSH для размещения через интерфейс

    Присвоить более высокий приоритет определенному процессу по умолчанию

    UNIX: нужно заменить последнюю строку на файле, а также удалить лишнюю пустую строку в конце

    Как узнать, поддерживает ли bash библиотеку readline?

    Слияние дублированных строк, которые имеют одинаковые первые три поля

    Netcat работает не так, как ожидалось, при удаленном выполнении в неинтерактивной оболочке

    Управление стандартным принтером пользователей в качестве администратора

    Понять «IFS = read -r line»?

    Linux и Unix - лучшая ОС в мире.