Как ничего не сделать навсегда изящным способом?

поведение zsh немного отличается здесь, чем большинство других оболочек. Другие оболочки, как удар, пытаются развернуть подстановочные знаки. Если они не могут расшириться ни до чего, что они передают литеральную строку (содержащий подстановочные знаки) к приложению вместо этого. Но zsh не делает этого (хорошо, существует опция для этого, чтобы сделать это или не). zsh распечатает ту ошибку и не выполнит команду. Можно переопределить это путем выхода из подстановочного знака, если Вы действительно хотите его, передал приложению. В этом случае Вы делаете, так как Вы хотите, чтобы другая оболочка стороны развернула его. Так использование:

scp remotehost:\*.txt .

Это - на самом деле корректное поведение, с тех пор если бы у Вас действительно были некоторые локальные *.txt файлы в Вашем доме, то они были бы расширены до имени, которое не могло бы существовать на удаленном. Это не то, что Вы хотите.

84
12.07.2012, 21:42
9 ответов

В оболочках, которые их поддерживают (ksh, zsh, bash4), вы можете запустить программу как совместный процесс .

  • ksh : программа> вывод | &
  • zsh , bash : программа coproc> вывод

Это запускает программу в фоновом режиме с его вводом, перенаправленным из канала . Другой конец трубы открыт для оболочки.

Три преимущества этого подхода

  • без дополнительных процессов
  • вы можете выйти из сценария, когда программа умирает (используйте wait , чтобы дождаться этого)
  • program завершится (получите eof на его стандартном вводе, если оболочка завершится).
17
27.01.2020, 19:30

Я не думаю, что Вы собираетесь стать больше изящными, чем

tail -f /dev/null

то, что Вы уже предложили (предполагающий, что это использует inotify внутренне, не должно быть никакого опроса или пробуждений, таким образом, кроме того, чтобы быть нечетным взглядом, это должно быть достаточно).

Вам нужна утилита, которая будет работать неограниченно долго, сохранит ее stdout открытым, но ничего на самом деле не запишет в stdout и не выйдет, когда его stdin будет закрыт. Что-то как yes на самом деле записи к stdout. cat выйдет, когда его stdin закрывается (или независимо от того, что Вы перенаправляете в него, сделан). Я думаю sleep 1000000000d мог бы работать, но tail ясно лучше. Поле My Debian имеет a tailf это сокращает команду немного.

Выбирание другого подхода, как насчет того, чтобы запустить программу под screen?

78
27.01.2020, 19:30
  • 1
    мне нравится tail -f /dev/null приблизьтесь к лучшему и найдите это достаточно изящным также, так как использование команды соответствует намеченной цели вполне тесно. –  jw013 12.07.2012, 22:40
  • 2
    От strace tail -f /dev/null это кажется этим tail использование inotify и это пробуждения происходит в глупых случаях как sudo touch /dev/null. Грустно, что, кажется, нет никакого лучшего решения... Интересно, который был бы правом syscall для использования для реализации лучшего решения. –  a3nm 12.07.2012, 22:59
  • 3
    @a3nm syscall был бы pause, но это не выставляется непосредственно интерфейсу оболочки. –  Gilles 'SO- stop being evil' 13.07.2012, 01:25
  • 4
    P.T.: Я знаю о screen, но это должно выполнить несколько случаев программы из сценария оболочки для тестирования, таким образом с помощью screen немного излишества. –  a3nm 20.07.2012, 15:19
  • 5
    @sillyMunky Глупая Обезьяна, ответ WaelJ является неправильным (отправляет бесконечные нули в stdin). скидка с цены –  P.T. 22.07.2012, 21:07
sleep 2147483647 | program > output &

Да, 2^31-1 конечное число, и оно не будет работать навсегда, но я дам Вам 1 000$, когда сон наконец испытает таймаут. (Подсказка: один из нас будет мертв к тому времени.)

  • никакие временные файлы; проверить.
  • никакое активное ожидание или периодические пробуждения; проверить
  • никакие экзотические утилиты; проверить.
  • максимально короткий. Хорошо, это могло быть короче.
19
27.01.2020, 19:30
  • 1
    : $ сна ((64 #1 _____)) | программа> вывод и –  Diego Torres Milano 13.07.2012, 08:24
  • 2
    Это спит в течение 68 лет, это спит в течение 98 веков: sleep 2147483647d... –  agc 04.06.2017, 19:14

Перенаправление /dev/zero как стандартный вход!

program < /dev/zero > output &
-2
27.01.2020, 19:30
  • 1
    , Это дало бы его программе бесконечное число нулевых байтов..., которые, к сожалению, сделает это занятым циклом. игрок –  Jander 13.07.2012, 02:51
  • 2
    Это не истинный jander,/dev/zero никогда не будет закрываться, содержа открытую цепочку канала. Однако в плакате говорится, что он не берет в stdin, таким образом, никакие нули никогда не будут передаваться программе. Это не занятый цикл вообще, это - чистое ожидание. –  sillyMunky 22.07.2012, 20:38
  • 3
    извините, OP действительно использует stdin, таким образом, это вытрет его вход и будет тянуть из/dev/zero. Я должен читать в дважды следующий раз! Если бы OP не использовал stdin, то это было бы самым изящным решением, которое я видел и не был бы активным ожиданием. –  sillyMunky 22.07.2012, 20:46

бесконечность сна [112667] является самым ясным решением, о котором я знаю.

make
make install
modprobe r8192se_pci

Вы можете использовать [112668] бесконечность [112669], потому что [112670] сна [112671] принимает число с плавающей точкой [112672]*[112673], которое может быть [112674] десятичным [112675], [112676] шестнадцатеричным [112677], [112678] бесконечность [112679], или [112680] NaN[112681], согласно [112682] man strtod [112683].

enter image description here

* Это не является частью стандарта POSIX, так же как и [112684] хвост -f /dev/null[112685]. Однако он поддерживается в GNU coreutils (Linux) и BSD (используется на Mac) (очевидно, не поддерживается на более новых версиях Mac - см. комментарии)[112350].
50
27.01.2020, 19:30

Вы можете создать двоичный файл, который делает именно это, с помощью:

$ echo 'int main(){ pause(); }' > pause.c; make pause
9
27.01.2020, 19:30

Вот еще одно предложение с использованием стандартных утилит Unix, чтобы «ничего не делать бесконечно» .

sh -c 'kill -STOP $$' | program > output

Запускает оболочку, которая немедленно отправляет SIGSTOP , что приостанавливает процесс. Это используется как «вход» в вашу программу. Дополнением к SIGSTOP является SIGCONT , т.е. если вы знаете, что оболочка имеет PID 12345, вы можете kill -CONT 12345 , чтобы продолжить работу.

5
27.01.2020, 19:30

В Linux вы можете:

read x < /dev/fd/1 | program > output

В Linux, открыв / dev / fd / x, где x - дескриптор файла для записывающего конца канала, вы получите читающий конец канала, так что здесь то же самое как на стандартном вводе программы. Таким образом, read никогда не вернется, потому что единственное, что может писать в этот канал, - это он сам, а read ничего не выводит.

Он также будет работать во FreeBSD или Solaris, но по другой причине. Там открытие / dev / fd / 1 дает вам тот же ресурс, что и open на fd 1, как и следовало ожидать, и как и большинство систем, кроме Linux, так что записывающий конец канала. Однако во FreeBSD и Solaris каналы являются двунаправленными. Итак, пока программа не записывает на свой стандартный ввод (ни одно приложение не делает), read не получит ничего для чтения из этого направления канала.

В системах, где каналы не являются двунаправленными, чтение , вероятно, завершится ошибкой при попытке чтения из файлового дескриптора, доступного только для записи. Также обратите внимание, что не во всех системах есть / dev / fd / x .

2
27.01.2020, 19:30

Стефан Хазелас читать решение работает и в Mac OS X, если fd чтения открывается на / dev / fd / 1 .

# using bash on Mac OS X
# -bash: /dev/fd/1: Permission denied
read x </dev/fd/1 | cat >/dev/null
echo ${PIPESTATUS[*]}   #  1 0

exec 3<&- 3</dev/fd/1
read x 0<&3 | cat >/dev/null
echo ${PIPESTATUS[*]}   #  0 0

Чтобы иметь возможность убить tail -f / dev / null в сценарии (например, с помощью SIGINT), необходимо выполнить команду tail и подождать .

#!/bin/bash
# ctrl-c will kill tail and exit script
trap 'trap - INT; kill "$!"; exit' INT
exec tail -f /dev/null & wait $!
0
27.01.2020, 19:30

Теги

Похожие вопросы