2012-01-08 13 views
6

Esto es similar a another issue, pero solo quiero que make solicite un valor si estoy ejecutando un objetivo específico y no se ha especificado una variable obligatoria.¿Cómo se solicita la variable Makefile específica del destino si no está definida?

El código actual:

install-crontab: PASSWORD ?= "$(shell read -p "Password: "; echo "$$REPLY")" 
install-crontab: $(SCRIPT_PATH) 
    @echo "@midnight \"$(SCRIPT_PATH)\" [...] \"$(PASSWORD)\"" 

Esto se traduce en la siguiente salida y ningún indicador:

Password: read: 1: arg count 
@midnight [...] "" 

El punto importante aquí es que tengo que pedir única cuando se ejecuta este objetivo, y solo si la variable no se ha definido. No puedo usar un script configure, porque obviamente no debería almacenar contraseñas en un script de configuración, y porque este objetivo no es parte del procedimiento de instalación estándar.

Respuesta

6

Resulta que el problema era que Makefiles no utilizar la cotización Dash/estilo Bash, y que read integrado de Dash necesita un nombre de variable, a diferencia de Bash. código resultante:

install-crontab-delicious: $(DELICIOUS_TARGET_PATH) 
    @while [ -z "$$DELICIOUS_USER" ]; do \ 
     read -r -p "Delicious user name: " DELICIOUS_USER;\ 
    done && \ 
    while [ -z "$$DELICIOUS_PASSWORD" ]; do \ 
     read -r -p "Delicious password: " DELICIOUS_PASSWORD; \ 
    done && \ 
    while [ -z "$$DELICIOUS_PATH" ]; do \ 
     read -r -p "Delicious backup path: " DELICIOUS_PATH; \ 
    done && \ 
    (\ 
     CRONTAB_NOHEADER=Y crontab -l || true; \ 
     printf '%s' \ 
      '@midnight ' \ 
      '"$(DELICIOUS_TARGET_PATH)" ' \ 
      "\"$$DELICIOUS_USER\" " \ 
      "\"$$DELICIOUS_PASSWORD\" " \ 
      "\"$$DELICIOUS_PATH\""; \ 
     printf '\n') | crontab - 

Resultado:

$ crontab -r; make install-crontab-delicious && crontab -l 
Delicious user name: a\b c\d 
Delicious password: e f g 
Delicious backup path: h\ i 
no crontab for <user> 
@midnight "/usr/local/bin/export_Delicious" "a\b c\d" "e f g" "h\ i" 
$ DELICIOUS_PASSWORD=foo make install-crontab-delicious && crontab -l 
Delicious user name: bar 
Delicious backup path: baz 
@midnight "/usr/local/bin/export_Delicious" "a\b c\d" "e f g" "h\ i" 
@midnight "/usr/local/bin/export_Delicious" "bar" "foo" "baz" 

este código:

  • trata todos los caracteres de entrada como literales, por lo que funciona con espacios y barras invertidas,
  • evita problemas si el usuario presiona Ingrese sin escribir nada,
  • usa variables de entorno si existen, y
  • funciona ya sea que crontab esté vacío o no.
2

La respuesta de l0b0 me ayudó con un problema similar en el que quería salir si el usuario no ingresa 'y'. Terminé haciendo esto:

@while [ -z "$$CONTINUE" ]; do \ 
    read -r -p "Type anything but Y or y to exit. [y/N] " CONTINUE; \ 
done ; \ 
if [ ! $$CONTINUE == "y" ]; then \ 
if [ ! $$CONTINUE == "Y" ]; then \ 
    echo "Exiting." ; exit 1 ; \ 
fi \ 
fi 

Espero que ayude a alguien. Es difícil encontrar más información sobre el uso de la entrada del usuario para un if/else en un archivo MAKE.

+0

A menos que los ojos de la mina me engañen, ese bucle while se repetirá en lugar de usar la 'N 'predeterminada si simplemente presiona Enter. – l0b0

+0

Debería usar un [único signo igual en '['] (http://mywiki.wooledge.org/Bashism#Conditionals) – l0b0

+2

También puede simplificar la instrucción 'if':' if [$$ CONTINUE! = "Y "] && [$$ CONTINUAR! =" S "]; entonces'. O incluso '[$$ CONTINUE =" y "] || [$$ CONTINUE = "Y"] || (echo "Saliendo"; salida 1;) ' – l0b0

Cuestiones relacionadas