Как мога да разбера дали makefile се изпълнява от интерактивна обвивка?

Имам makefile, който изпълнява команди, което може да отнеме известно време. Бих искал тези команди да са разговорливи, ако изграждането е инициирано от интерактивна обвивка, но по-тихи, ако не (по-специално от 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
Съжалявам, че обсипвам парада ви, но това ви казва дали обвивката, която изпълнявате, е била стартирана интерактивно, но вътре в makefile, всяка обвивка, която стартирате, ще твърди, че се изпълнява неинтерактивно, дори ако 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. Бих искал да направя това с помощта на makefile като този:

VERBOSE = --verbose

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

all: bar baz
    foo $(foo_opts)

След това в задачата cron укажете:

make VERBOSE=

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

Едно малко предимство на тази техника е, че ще работи с всеки вариант на make; не зависи от никакво средство за създаване на GNU.

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