Как узнать, запускается ли make-файл из интерактивной оболочки?

У меня есть make-файл, который запускает команды, выполнение которых может занять некоторое время. Я бы хотел, чтобы эти команды были болтливыми, если сборка запускается из интерактивной оболочки, но тише, если нет (в частности, cron). Что-то вроде (псевдокода):

foo_opts = -a -b -c
if (make was invoked from an interactive shell):
    foo_opts += --verbose

all: bar baz
    foo $(foo_opts)

Это GNU make. Если особенности того, что я делаю, имеют значение, я могу отредактировать вопрос.


person Reid    schedule 23.11.2010    source источник


Ответы (5)


Это не строго определяет, вызывается ли он из интерактивной оболочки или нет, но для задания cron, в котором вывод перенаправляется в файл, ответ на этот вопрос будет таким же, как для Как определить, выполняется ли мой сценарий оболочки через канал?:

if [ -t 0 ]
then
    # input is from a terminal
fi

Изменить: чтобы использовать это для установки переменной в Makefile (то есть в GNU make):

INTERACTIVE:=$(shell [ -t 0 ] && echo 1)

ifdef INTERACTIVE
# is a terminal
else
# cron job
endif
person PleaseStand    schedule 23.11.2010
comment
В основном ... это часто самая надежная проверка того, подключена ли программа к терминалу; мало кто запускает make </dev/null. - person Jonathan Leffler; 23.11.2010

http://www.faqs.org/faqs/unix-faq/faq/part5/section-5.html

5.5) Как узнать, запущена ли интерактивная оболочка?

  In the C shell category, look for the variable $prompt.

  In the Bourne shell category, you can look for the variable $PS1,
  however, it is better to check the variable $-.  If $- contains
  an 'i', the shell is interactive.  Test like so:

      case $- in
      *i*)    # do things for interactive shell
              ;;
      *)      # do things for non-interactive shell
              ;;
      esac
person Naveen    schedule 23.11.2010
comment
Извините за дождь на вашем параде, но это говорит вам, была ли запущенная вами оболочка запущена в интерактивном режиме, но внутри make-файла любая запущенная вами оболочка будет утверждать, что она запускается неинтерактивно, даже если make сам запускается из интерактивного оболочка. Доказательство: makefile содержит "all:;echo "Shell: $$-"" и запустите "make", и он не будет включать "i" в выводе. (На моем Mac я получил «hBc» из «make» по сравнению с «himBH» из моей интерактивной оболочки.) - person Jonathan Leffler; 23.11.2010
comment
Хм ... возможно OP может проверить интерактивность в оболочке, которая вызывает make, и установить переменную окружения, которая может быть записана в make-файле. - person Naveen; 23.11.2010
comment
Сортировка переменных окружения в основном работает, но не очень удовлетворительна. - person Jonathan Leffler; 23.11.2010

Я не думаю, что вы легко узнаете. Я предлагаю принять альтернативную стратегию, возможно, подавив подробный вывод задания cron. Я бы сделал это с помощью такого make-файла:

VERBOSE = --verbose

foo_opts = -a -b -c ${VERBOSE}

all: bar baz
    foo $(foo_opts)

Затем в задании cron укажите:

make VERBOSE=

Эта спецификация командной строки VERBOSE переопределяет спецификацию в make-файле (и не может быть изменена make-файлом). Таким образом, специализированная задача (задание cron), которую вы настраиваете один раз и используете много раз, будет выполняться без подробного вывода; общая задача построения будет выполняться подробно (если вы не решите переопределить подробность в командной строке).

Одним из незначительных преимуществ этого метода является то, что он будет работать с любым вариантом make; он не зависит от каких-либо средств GNU Make.

person Jonathan Leffler    schedule 23.11.2010

Я не совсем понимаю, что означает «интерактивный». Вы имеете в виду, если у вас есть действующий /dev/tty? Если да, то вы можете это проверить. Однако большинство из нас проверяет isatty на stdin, потому что он отвечает на вопросы, которые мы хотим знать: есть ли там кто-нибудь, чтобы что-то напечатать.

person tchrist    schedule 23.11.2010
comment
Проблема в том, что вы хотите, чтобы ребенок знал, является ли родитель интерактивным, и вы не можете сделать это таким образом, поскольку он возвращает статус дочернего элемента при запуске в дочернем элементе. - person Dennis Williamson; 23.11.2010

Просто примечание: вы также можете увидеть соответствующее обсуждение, который у меня был об обнаружении перенаправления STDOUT из Makefile.

Я считаю, что это будет полезно читателям этого вопроса - краткое содержание:

-include piped.mk

all:    piped.mk
ifeq ($(PIPED),1)
    @echo Output of make is piped because PIPED is ${PIPED}
else
    @echo Output of make is NOT piped because PIPED is ${PIPED}
endif
    @rm -f piped.mk

piped.mk:
    @[ -t 1 ] && PIPED=0 || PIPED=1 ; echo "PIPED=$${PIPED}" > piped.mk

$ make
Output of make is NOT piped because PIPED is 0

$ make | more
Output of make is piped because PIPED is 1

В своем ответе я объясняю, почему [-t 1] должен выполняться в действии, а не в назначении переменной (как в рекомендуемом ответе здесь), а также различные ловушки, связанные с переоценкой сгенерированного Makefile (т.е. piped.mk выше ).

Термин интерактивный в этом вопросе, по-видимому, подразумевает перенаправление STDIN ... и в этом случае замена [ -t 1 ] на [ -t 0 ] в моем коде выше должна работать как есть.

Надеюсь это поможет.

person ttsiodras    schedule 23.05.2017