Понимание концепции «замены процесса»

Пробовал использовать Python, все работает нормально

#!/usr/bin/python
import re
g=re.compile(r'[0-9]*\.[0-9]*\.[0-9]*')
m=open('u.txt','r')
for i in m:
    if re.search(g,i):
        print i.strip().replace("#","")

вывод 1

92.168.54.144  name1
192.168.54.144   name2
192.168.54.143   name3
-1
20.03.2021, 16:43
1 ответ

Важный факт :задействованы две оболочки

Во-первых, обратите внимание, что задействованы две оболочки. Есть внешний Bash, в котором вы работаете, вы вызываете в нем (тип )bash <(wget -O - URL). И есть внутренний Bash, который запускается как дочерний процесс внешнего Bash, когда команда выполняется.

Другими словами, внешний Bash принимает bash <(wget -O - URL)как команду и порождает внутренний Bash. Я буду различать два, где это уместно.


Важный факт :существует несколько способов запуска кода с помощью Bash

Есть несколько способов заставить (внутренний )Bash запустить некоторый код:

  1. bashможет читать код со своего стандартного ввода:

    echo 'date; sleep 2; date' | bash
    

    Стандартный ввод может быть консолью. Например. интерактивный bashвы обычно работаете при чтении с консоли, но на самом деле он читает со своего стандартного ввода, потому что консоль является его стандартным вводом.

  2. bashможет читать код из файла:

    bash /path/to/some/file
    

    (Путь может быть относительным.)

  3. bashможет читать код из аргумента строки команды -:

    bash -c 'date; sleep 2; date'
    

Контекст

В комментарии вы сказали, что контекст этот вопрос . Мой ответ там посоветовал заменить:

wget -O - URL | bash

с

bash <(wget -O - URL)

Первая команда заставляет внутренний bashчитать из стандартного ввода. Что вы, кажется, не поняли, так это то, что вторая команда заставляет внутренний bashчитать из файла, который не является его стандартным вводом.


Что происходит с<(…)

Когда вы запускаете bash <(wget -O - URL)в Bash, внешний Bash заменяет <(…)путем к какому-то файлу . После замены фактическая выполняемая команда может выглядеть как:

bash /dev/fd/63

Это порождает внутренний Bash. Он открывается /dev/fd/63так же, как открывается /path/to/some/file.

Благодаря «волшебству» подстановки процесса /dev/fd/63— это канал, уже подключенный к wget -O - URL.

Примечание :в системе, где /dev/fdнедоступен, внешний Bash будет использовать действительно именованный канал (, например. /tmp/sh-np.pldKay), чтобы настроить это.


Сходство

Соединение от wgetк (внутреннему)bashаналогично в обоих случаях. Когда вы запускаете wget -O - URL | bash, bashсчитывает код со своего стандартного ввода, который является каналом, в который wgetзаписывает. Когда вы запускаете bash <(wget -O - URL), bashчитает код из другого файла (, то есть не из его стандартного ввода ), который является каналом wget. В обоих случаях внешний Bash устанавливает канал.


Разница

Разница в том, что при подстановке процесса стандартный ввод внутреннего Bash не используется для передачи ему кода. Стандартный ввод можно использовать для другой цели. Например. стандартный ввод может быть консолью, и readв коде может читать из нее.


Ответы на ваши явные вопросы

  • What problem/s this concept was invented to solve

    Когда команда ожидает имя пути (путь к файлу )и вы хотите передать что-то вместо предоставления обычного файла, вы можете создать именованный канал и достичь цели. Для этого нужно фактически создать канал (mkfifo), подключить к нему что-то (в фоновом режиме или в другой консоли ), запустить команду и, наконец, удалить именованный канал(rm).

    При замещении процесса Bash обрабатывает конвейер. Это удобно.

  • What process is being substituted and with what?

    В bash <(wget -O - URL)синтаксис <(wget -O - URL)заменяется на путь к какому-то файлу, только потом выполняется команда (и она bash /dev/fd/63или аналогичная ). Внешний Bash подготавливает файл, поэтому чтение из него означает чтение того, чтоwget -O - URL(пишет процесс ). Файл на самом деле является каналом, а не обычным файлом.

  • Is it also named "preserving stdin" and if so why?

    «Сохранение стандартного ввода» происходит, но это не альтернативное имя для подстановки процесса. Это не формальное название того, что происходит.

    Когда вы запускаете (inner)bash …в (external )Bash, внутренний Bash получает свой stdin, унаследованный от внешнего Bash (, то есть это тот же файл ). Стандартный ввод может быть консолью.

    Но если вы вместо этого запустите wget … | bash …, внутренний Bash увидит данные из wgetна своем собственном стандартном вводе. Теперь некоторая часть внутреннего Баша (, например. встроенныйread)или какой-либо дочерний элемент внутреннего Bash может захотеть прочитать что-то из стандартного ввода. Они ожидают ввода с консоли или чего-то еще, но не код, который должен выполнять внутренний Bash. Но поскольку стандартный ввод внутреннего Bash является конвейером из wget, встроенные функции будут использовать его, а дочерние процессы наследуют его как свои стандартные вводы. Они не наследуют стандартный ввод внешнего Bash.

    Используя подстановку процесса вместо передачи кода через стандартный ввод (внутреннего )bash, вы делаете стандартный ввод внешнего Bash доступным для встроенных и дочерних модулей внутреннего Bash. Вы сохраняете стандартный ввод внешнего Bash для встроенных и дочерних модулей внутреннего Bash. В то же время вы защищаете поток кода, который читает и выполняет внутренний Bash, от чтения его встроенными или дочерними элементами.

    Это работает только потому, что bashпозволяет предоставить код в файле, указанном в качестве аргумента командной строки. Если бы (внутренний )Bash поддерживал чтение кода только из стандартного ввода, вам пришлось бы предоставлять код через его стандартный ввод. В таком случае замена процесса не может решить вашу проблему .

1
28.04.2021, 22:58

Теги

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