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을 실행 sh하면 bash코드(편집하다, 위의 내용을 놓쳐서 죄송합니다 . 많은 시스템에는 전혀 포함 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호출 shell 을 사용하는 구현 의 경우 -e). 당신에게 필요한 것은 입니다 ||true. 여기서는 errexit필요한 경우 자체 오류 처리를 사용하거나 수행 하지 않습니다 || exit.
  • &백슬래시 와 s:pattern:repl:구분 기호(여기 )를 피해야 합니다 :. 그렇지 않으면 작동하지 않습니다(그리고 불쾌한 부작용이 있을 수 있습니다).
  • sed ... < file > file시작하기 전에 잘리므로 이 작업을 수행할 수 없습니다 file. sed일부 sed구현에서는 -ior -i ''옵션을 지원합니다. 또는 perl -pi.perl -pi

    여기를 이용하면 더 좋을 것 같아요하나는 입력이고 마지막 하나는 출력입니다.

여전히 더 이상 질문이 해결되지 않습니다.

  • 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

관련 정보