К сожалению, это не может быть безопасно, когда файловая система, которой Вы создаете резервную копию как это, смонтирована. Рассмотрите такую ситуацию:
Ваше резервное копирование является половиной сделанного пути (т.е. первая половина раздела уже записана в файл резервной копии.
Теперь Вы (или некоторая программа) делаете копию файла, который, оказывается, расположен на другой половине раздела. Filesystem ничего не знает о Вас процесс резервного копирования, но он решает, что существует некоторое пространство, оставленное в начале раздела, и это - то, где Ваша копия файла сделана. Obviosly, Ваше резервное копирование не будет содержать этот файл.
Теперь, так как Вы думаете, что у Вас есть копия этого файла, Вы решаете, что Вам не нужен исходный файл, и удаляет его. И право после этого, Ваш процесс резервного копирования прибывает в место, где этот файл был и информация о записи к файлу резервной копии, что этот файл был удален.
Как Вы могли бы ожидать, Вы заканчиваете без любой копии этого файла в Вашем резервном копировании. Это - просто пример, и это не худшая вещь, которая могла произойти.
Нет никаких "правил" как таковых. Некоторые программы берут данные из 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
.
Если выполняемая команда прочитает ее вход, то можно подключиться к ней, если нет, то нет.
.Существуют два общих способа предоставления входных данных программам:
kill
использует только аргументы командной строки. Он не считывается со STDIN.
Такие программы, как grep
и awk
читают из STDIN (если в качестве аргументов командной строки не указаны имена файлов) и обрабатывают данные в соответствии со своими аргументами командной строки (шаблон, операторы, флаги, ...).
Можно только подключать к STDIN другие процессы, а не аргументы командной строки.
Общее правило заключается в том, что программы используют STDIN для обработки произвольного количества данных. Все дополнительные входные параметры или, если их обычно мало, передаются с помощью аргументов командной строки. Если командная строка может быть очень длинной, например, для длинных текстов программ awk
, то часто есть возможность прочитать их из дополнительных программных файлов (-f
опция awk
).
Для использования STDOUT программ в качестве аргументов командной строки используйте $(...)
или в случае большого количества данных xargs
. find
также может это сделать непосредственно с помощью -exec .... {} +
.
Для полноты: Для записи аргументов командной строки в STDOUT используйте echo
.
Это интересный вопрос, и он касается части философии 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.
Вероятно, можно было бы объединить эти два аспекта: Фильтр - это программа, входные данные которой не имеют семантического значения для программы.
Я уверен, что где-то читал об этой философии, но на данный момент я не помню никаких источников, извините. Если у кого-то есть какие-то источники, пожалуйста, отредактируйте.
kill
и rm
не требуют стандартного ввода.
Для kill
и rm
пользователи предоставляют свою настроенную информацию в качестве аргумента, а $(cmd)
помогает взять STDOUT cmd
и преобразовать его в информационный аргумент.
Для grep
и awk
пользователи указывают аргументы и, кроме того, также STDIN
или обычный файл, который будет обрабатываться командой. STDIN
можно передавать с помощью конвейера |
или путем ввода вручную.
Прочтите руководство или исходные коды. И если вы не найдете ничего нужного, вы можете провести простой, но, возможно, опасный тест :
.Просто введите интересующую вас команду с аргументами, которые вы уже поняли, и посмотрите, не произойдет ли ничего при выполнении команды pause (). Если он приостанавливается, он фактически ожидает STDIN (, вы можете попробовать cat
и echo
, чтобы увидеть разные ). Вы вручную набираете Ctrl-D
, и команда продолжает (, показывает результаты или ошибки )и возвращает результат. Такой команде в этой ситуации нужен STDIN (с предоставленными вами аргументами ).
Одна и та же команда может не нуждаться в STDIN в разных ситуациях (например, cat
ожидает STDIN, а cat file.txt
нет ).