Как мне заставить `make` запрашивать у пользователя пароль и сохранять его в переменной Makefile?

Я пишу Makefile, и для некоторых команд, запускаемых makefile, требуется пароль. Я хотел бы дать пользователю возможность либо передать это как переменную Makefile, используя make PASSWORD=password, либо, если пользователь не передаст ее, запросить у пользователя это и сохранить свой ответ в указанной переменной Makefile.

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

Как прочитать что-то от пользователя и сохранить в переменной?

Я пробовал следующее:

PASSWORD ?= $(shell read -s -p "Password: " pwd; echo $pwd)

но подсказка никогда не печатается. Я также пробовал echo "Password: " внутри оболочки, но это тоже не печатается.

Любые идеи?

Изменить:

Чтобы уточнить, пароль нужно установить для конкретной цели, поэтому у меня что-то вроде этого:

PASSWORD := 

my-target: PASSWORD ?= $(shell read -s -p "Password: " pwd; echo $$pwd)

my-target:
    # rules for mytarget that use $(PASSWORD)

Редактировать 2:

Я нашел проблему. Когда я устанавливаю PASSWORD := в верхней части скрипта, он устанавливает PASSWORD в пустую строку, а это, в свою очередь, приводит к тому, что ?= пропускается (поскольку PASSWORD) уже установлено.


person bluesmoon    schedule 19.12.2013    source источник
comment
Какой команде нужен пароль? сш? Не могли бы вы вместо этого использовать вход без пароля по ssh? askubuntu .com/questions/46930/   -  person Digital Trauma    schedule 19.12.2013
comment
нет, не сш. Мне нужно запустить curl 3 раза для службы, требующей аутентификации. curl может запросить собственный пароль, но я бы не стал заставлять пользователя вводить его 3 раза.   -  person bluesmoon    schedule 19.12.2013
comment
Я чувствую, что незашифрованные пароли в переменных Make могут быть уязвимы для эксплуатации. Я не уверен, как это использовать, но злоумышленнику может быть легко сбросить переменные make-файла (make -pn) и получить этот пароль. Просто говорю' ;-)   -  person Digital Trauma    schedule 19.12.2013
comment
Этот пользователь будет тем же пользователем, который запускает make и вводит пароль, если только другой пользователь не может получить доступ к пространству памяти команды, запущенной первым пользователем... в этом случае все ставки сняты, и ваша ОС полностью скомпрометирована. .   -  person bluesmoon    schedule 19.12.2013
comment
Да, если это пароль curl, я не знаю другого способа справиться с ним, кроме того, что вы делаете. Я предполагаю, что наихудший сценарий, о котором я беспокоюсь, это то, что кому-то нужно будет отлаживать ваш Makefile в будущем и сбрасывать make -pn журналов куда-то на диск. Затем злоумышленник увидит открытый пароль в журнале сборки.   -  person Digital Trauma    schedule 19.12.2013


Ответы (2)


Несколько вещей:

  • $ для разыменования переменной оболочки pwd интерпретируется make. Вы можете избежать этого из make с помощью $$
  • make вызывает оболочку как Posix-совместимую /bin/sh вместо /bin/bash. Таким образом, опция -s для read не поддерживается.

Попробуйте это вместо этого:

PASSWORD ?= $(shell bash -c 'read -s -p "Password: " pwd; echo $$pwd')

Это сработало для меня на Ubuntu 12.04/GNU make 3.81/bash 4.2.25(1)

И на OSX 10.8.5/make 3.81/bash 3.2.48(1):

$ cat Makefile 
PASSWORD ?= $(shell bash -c 'read -s -p "Password: " pwd; echo $$pwd')

all:
    echo The password is $(PASSWORD)
$ make
Password: echo The password is 1234
The password is 1234
$ 

Обновление — @user5321531 указал, что мы можем использовать POSIX sh вместо bash и временно подавить эхо с помощью stty:

PASSWORD ?= $(shell stty -echo; read -p "Password: " pwd; stty echo; echo $$pwd)
person Digital Trauma    schedule 19.12.2013
comment
не работает на MacOSX/GNU Make 3.81/bash 3.2.48. Он отказывается печатать приглашение. - person bluesmoon; 19.12.2013
comment
@bluesmoon - мне кажется, на OSX он работает так же, как и на Ubuntu. Возможно, я что-то упускаю? Я добавил в ответ свой тестовый Makefile и журнал консоли. - person Digital Trauma; 19.12.2013
comment
А, я вижу разницу. Мне нужна переменная, установленная только для конкретной цели. Я отредактирую вопрос с примером. - person bluesmoon; 19.12.2013
comment
Хорошо, теперь я вижу свою проблему. Я инициализировал PASSWORD пустой строкой в ​​верхней части моего Makefile, поэтому он полностью пропускал часть ?=. Спасибо за ваши комментарии. Еще одна вещь, которую я пропустил, это $$pwd. - person bluesmoon; 19.12.2013
comment
Небольшой комментарий, если используется оболочка POSIX, чтобы предотвратить вывод эха на экран stty -echo и повторно включить stty echo. - person user5321531; 26.06.2015
comment
Быстрый вопрос: как заставить make не спрашивать пароль несколько раз, если он используется более чем в одном месте? - person joebeeson; 24.07.2019
comment
@joeb, пожалуйста, посмотрите мой ответ ниже: stackoverflow.com/a/61948795/1979230 - person Brian Hannay; 22.05.2020
comment
SHELL := /bin/bash, обычно в верхней части вашего Makefile, заставит make использовать bash, а не sh по умолчанию. - person sqqqrly; 28.02.2021

Чтобы ответить @joeb на вопрос:

$ make; echo "---Makefile---"; cat Makefile
Password: <hidden>
test
test
---Makefile---
all: first second
PASSWORD ?= $(shell read -s -p "Password: " pass; echo $$pass)
define formatted
first:
        @echo $1
second:
        @echo $1
endef

$(eval $(call formatted,$(PASSWORD)))
person Brian Hannay    schedule 22.05.2020