Makefileで `read`コマンドが機能しません。

Makefileで `read`コマンドが機能しません。

3つのタスクを実行するmakeスクリプトがあります。

  1. MySQLデータベースのインポート
  2. モバイルプロフィール
  3. 構成ファイルの構成

このためには、スクリプトには3つの入力が必要です。

  1. MySQLホスティング
  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バグを解決することですが、提案、バグレポート、または提案があれば感謝します。私は彼らに報酬を与えることができます。

ご協力ありがとうございます!

答え1

makeそこにシェルと変数を混ぜています。makeシェルとその両方が対応$する変数を使用します。

Makefileでは、変数は単一文字変数または$(var)シェルに表示されます。$v$var${var}

$varしかし、Makefileに書くとmake理解されます$(v)ar。リテラルをシェルに渡すには、 in または で$入力しなければシェルの or になります。$$$$var$${var}$var${var}

またmake、実行するshbashコード(編集する、上記を見逃して申し訳ありません。多くのシステムにはまったく含まれSHELL := /bin/bashていないので(GNUのみの場合)、その構文を使用する必要があります。 、/文法ではなく構文ではありません。bash/binbash:=shecho -nread -szshbashsh

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
  • &バックスラッシュとs:pattern:repl:区切り記号(ここ)を避ける必要があります:。それ以外の場合は機能しません(そして不快な副作用があるかもしれません)。
  • sed ... < file > file始める前に切り捨てるため、これを行うことはできませんfilesedいくつかのsed実装は-ior-i ''オプションをサポートしています。または。perl -piperl -pi

    ここを使うともっといいと思います。はい1 つは入力、最後の 1 つは出力です。

それでも質問は解決されません。

  • config.php現在の権限から派生した権限で新しい権限が作成されますumask世界中で読むことができる実行中のユーザーが所有しますmake。ディレクトリが特に制限されていない場合、umaskファイルに機密情報が含まれているため、所有権を調整および/または変更する必要があります。includes
  • パスワードに"文字が含まれていると、パスワードが破損している可能性があります(今回はphp)。エラーを返してこれを抑制するか、phpそのファイルの正しい構文で別のエスケープレイヤーを追加しようとします。バックスラッシュと同様の問題が発生する可能性があり、ASCII以外の文字または制御文字を除外することもできます。
  • コマンドラインからパスワードを渡すことは、通常mysqlパスワードが出力に表示されることを意味するので、それは悪い考えですps -f。使用するのが最善です。

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

    printf組み込みのためps出力には表示されません。

  • $hostこの変数は使用されません。

  • ユーザーにこのようなメッセージを表示することは、スクリプトを簡単に自動化できないことを意味します。パラメータから入力を取得するか、環境変数を使用できます(パスワードに適しています)。

答え2

Makefileのどの機能も使用していません。単一のシェルにこれらの行を書き込もうとしますか?

次のMakefileで

    echo $username;\
    echo $password;\

makeは(空の変数)+(文字列)$usernameとして解釈されます。$username

Makefileに保存したい場合$username$$username

関連情報