Почему некоторые команды не читают из своего входа стандарта?

К сожалению, это не может быть безопасно, когда файловая система, которой Вы создаете резервную копию как это, смонтирована. Рассмотрите такую ситуацию:

  • Ваше резервное копирование является половиной сделанного пути (т.е. первая половина раздела уже записана в файл резервной копии.

  • Теперь Вы (или некоторая программа) делаете копию файла, который, оказывается, расположен на другой половине раздела. Filesystem ничего не знает о Вас процесс резервного копирования, но он решает, что существует некоторое пространство, оставленное в начале раздела, и это - то, где Ваша копия файла сделана. Obviosly, Ваше резервное копирование не будет содержать этот файл.

  • Теперь, так как Вы думаете, что у Вас есть копия этого файла, Вы решаете, что Вам не нужен исходный файл, и удаляет его. И право после этого, Ваш процесс резервного копирования прибывает в место, где этот файл был и информация о записи к файлу резервной копии, что этот файл был удален.

Как Вы могли бы ожидать, Вы заканчиваете без любой копии этого файла в Вашем резервном копировании. Это - просто пример, и это не худшая вещь, которая могла произойти.

19
04.07.2014, 02:09
4 ответа

Нет никаких "правил" как таковых. Некоторые программы берут данные из STDIN, а некоторые нет. Если программа может принимать входные данные из STDIN, то ее можно связать, если нет, то нет.

Обычно можно определить, будет ли программа принимать входные данные или нет, подумав о том, что она делает. Если задача программы состоит в том, чтобы как-то манипулировать содержимым файла (например, grep, sed, awk и т.д.), то обычно она принимает входные данные из STDIN. Если его задачей является манипулирование самим файлом (например, mv, rm, cp) или процессом (например, , sed, awk и т.д.), то он обычно получает входные данные из STDIN. убить , из) или вернуть информацию о чем-то (например, top, найти , ps), то это не так.

Другой способ мышления - это разница между аргументами и входными данными. Например:

mv foo bar

В команде выше mv не имеет входа как такового. Было приведено два аргумента. Он не знает и не заботится о том, что находится в любом из файлов, он просто знает, что это его аргументы, и он должен манипулировать ими.

С другой стороны

sed -e 's/foo/bar/' < file
--- -- ------------   ----
 |   |       |          |-> input
 |   |       |------------> argument        
 |   |--------------------> option/flag/switch
 |------------------------> command

Здесь sed был задан не только аргумент, но и его значение. Так как он принимает input, он может прочитать его из STDIN и может быть передан на конвейер.

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

cat file

Здесь file - это аргумент, который был передан в cat. Если быть точным, то имя файла имя файл является аргументом. Однако, так как cat - это программа, которая манипулирует содержимым файлов, то на ее входе находится все, что находится внутри файла cat.

Это можно проиллюстрировать, используя strace, программу, которая отслеживает системные вызовы, сделанные процессами. Если запустить cat foo через strace, то мы увидим, что открыт файл foo:

$ strace cat foo 2| grep foo
execve("/bin/cat", ["cat", "foo"], [/* 44 vars */]) = 0
open("foo", O_RDONLY)     

Первая строка выше показывает, что была вызвана программа /bin/cat и ее аргументами были cat и foo (первый аргумент - всегда сама программа). Позже аргумент foo был открыт только в режиме чтения. Теперь сравните его с

$ strace ls foo 2| grep foo 
execve("/bin/ls", ["ls", "foo"], [/* 44 vars */]) = 0
stat("foo", {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
lstat("foo", {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
write(1, "foo\n", 4foo

Здесь также ls взял сам себя и foo в качестве аргументов. Однако, нет вызова open, аргумент не рассматривается как входной. Вместо этого ls вызывает системную библиотеку stat (что не то же самое, что команда stat) для получения информации о файле foo.

Если выполняемая команда прочитает ее вход, то можно подключиться к ней, если нет, то нет.

.
5
27.01.2020, 19:45

Существуют два общих способа предоставления входных данных программам:

  • предоставлять данные в STDIN процессов
  • указывать аргументы командной строки

kill использует только аргументы командной строки. Он не считывается со STDIN. Такие программы, как grep и awk читают из STDIN (если в качестве аргументов командной строки не указаны имена файлов) и обрабатывают данные в соответствии со своими аргументами командной строки (шаблон, операторы, флаги, ...).

Можно только подключать к STDIN другие процессы, а не аргументы командной строки.

Общее правило заключается в том, что программы используют STDIN для обработки произвольного количества данных. Все дополнительные входные параметры или, если их обычно мало, передаются с помощью аргументов командной строки. Если командная строка может быть очень длинной, например, для длинных текстов программ awk, то часто есть возможность прочитать их из дополнительных программных файлов (-f опция awk).

Для использования STDOUT программ в качестве аргументов командной строки используйте $(...) или в случае большого количества данных xargs. find также может это сделать непосредственно с помощью -exec .... {} +.

Для полноты: Для записи аргументов командной строки в STDOUT используйте echo.

17
27.01.2020, 19:45

Это интересный вопрос, и он касается части философии Unix / Linux.

Итак, в чем разница между такими программами, как grep , sed , sort с одной стороны и kill , ] rm , ls с другой стороны? Я вижу два аспекта.

Аспект фильтра

  • Первый вид программ также называется фильтрами . Они принимают входные данные либо из файла, либо из STDIN, модифицируют его и генерируют некоторые выходные данные, в основном в STDOUT. Они предназначены для использования в канале с другими программами в качестве источников и пунктов назначения.

  • Второй тип программ воздействует на ввод, но вывод, который они дают, часто не связан с вводом. kill не выводит, когда работает регулярно, как и ls . Просто есть возвращаемое значение, чтобы показать успех. Обычно они не принимают входные данные из STDIN, но в основном выдают выходные данные в STDOUT.

Для таких программ, как ls , аспект фильтра работает не так хорошо. Конечно, у него может быть вход (но он не нужен), и выход тесно связан с этим входом, но не работает как фильтр. Однако для таких программ другой аспект все еще работает:

Семантический аспект

  • Для фильтров их входные данные не имеют семантического значения . Они просто читают данные, изменяют данные, выводят данные. Не имеет значения, является ли это списком числовых значений, некоторыми именами файлов или исходным кодом HTML. Значение этих данных дает только код , который вы предоставляете фильтру: регулярное выражение для grep , правила для awk или программа Perl.

  • Для других программ, таких как kill или ls , их входные данные имеют значение , означающее , обозначение . kill ожидает номера процессов, ls ожидает имена файлов или пути. Они не могут обрабатывать произвольные данные и не предназначены для этого. Многие из них даже не нуждаются в вводе или параметрах, например ps . Обычно они не читают из STDIN.

Вероятно, можно было бы объединить эти два аспекта: Фильтр - это программа, входные данные которой не имеют семантического значения для программы.

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

16
27.01.2020, 19:45
  • Почему это не работает с kill или rm?

killи rmне требуют стандартного ввода.

  • В чем разница между вводом kill, вводом rm с помощью grep и вводом awk?

Для killи rmпользователи предоставляют свою настроенную информацию в качестве аргумента, а $(cmd)помогает взять STDOUT cmdи преобразовать его в информационный аргумент.

Для grepи awkпользователи указывают аргументы и, кроме того, также STDINили обычный файл, который будет обрабатываться командой. STDINможно передавать с помощью конвейера |или путем ввода вручную.

  • Есть ли правила?

Прочтите руководство или исходные коды. И если вы не найдете ничего нужного, вы можете провести простой, но, возможно, опасный тест :

.

Просто введите интересующую вас команду с аргументами, которые вы уже поняли, и посмотрите, не произойдет ли ничего при выполнении команды pause (). Если он приостанавливается, он фактически ожидает STDIN (, вы можете попробовать catи echo, чтобы увидеть разные ). Вы вручную набираете Ctrl-D, и команда продолжает (, показывает результаты или ошибки )и возвращает результат. Такой команде в этой ситуации нужен STDIN (с предоставленными вами аргументами ).

Одна и та же команда может не нуждаться в STDIN в разных ситуациях (например, catожидает STDIN, а cat file.txtнет ).

0
27.01.2020, 19:45

Теги

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