Если вы заранее знаете, что хотите следить за тем, что делает программа, интерфейс ядра, такой как sysdig
или SystemTap
, может записывать контрольный журнал (или, возможно, strace
, но это будет медленный и потребует идеальной оболочки вокруг программы для трассировки, и, надеюсь, sudo
никогда не будет запущен... ). Вам также необходимо учитывать, что происходит, когда какая-либо другая программа создает выходные данные в рамках рассматриваемой программы :Должен ли также отслеживаться любой дочерний процесс?
perl -e 'qx(echo subshell-io > foo)'
Контрольный журнал каждого файла, затронутого каждой программой (, плюс другие метаданные, такие как пользователь и группа (s ), родительский pid и т. д. ), безусловно, возможен. Однако это может быть дорого в настройке, дорого в создании и дорого в обслуживании. Вероятно, потребуются некоторые средства фильтрации записей, чтобы исключить (некоторые, но, возможно, не все)/tmp
записи в каталог, чтобы, возможно, объединить несколько вызовов записи passwd.tmp
/ rename("passwd.tmp","passwd")
в одну логическую операцию, а также как вы обрабатываете случай, когда интересующая вас программа изменяет, скажем,/etc/passwd
(среди многих других возможных общих файлов ОС ), которые вы, вероятно, затем не хотите удалять вслепую при очистке после программы... или как вы справляетесь с делегированным Ввод-вывод, где ваша программа использует dbus, а затем какой-то другой процесс из-за какого-то случайного не -сообщения ввода-вывода по dbus генерирует ввод-вывод в другом месте из-за вашей программы...
Так как вы можете иметь более одного значения, разделенного пробелом -в строке, использование awk
немного сложно. Это абсолютно возможно в awk, но проще вместо этого использовать что-то вроде Perl:
$ perl -lne '
if(/(^| )server / || eof){
print join " ",@ll if $ll[0];
@ll=();
}
/^(listen|root|server_name)\s+(\S[^;]+)/ && push @ll,$2' file
80 domain1.com www.domain1.com html
80 domain2.com www.domain2.com /var/www/virtual/big.server.com/htdocs
-lne
означает «прочитать входной файл построчно (-n
), удалить завершающие символы новой строки и добавить новую строку к каждому print
вызову(-l
)и запустить сценарий, заданный -e
в каждой строке».
Код:
if(/(^| )server / || eof){
:этот раздел запустится, если текущая строка содержит слово server
, окруженное пробелами, или в начале строки.
print join " ",@ll if $ll[0];
:если в настоящее время что-то хранится в массиве@ll
(поэтому, если первый элемент массива, $ll[0]
, определен ), выведите содержимое массива, соединенного пробелом.
@ll=();
:очистить массив, чтобы мы могли получить информацию о следующем сервере.
/^(listen|root|server_name)\s+(\S[^;]+)/ && push @ll,$2'
:если эта строка начинается с одного из ключевых слов, а затем содержит один или несколько пробельных символов, найдите первый не -пробельный символ и как можно больше не-;
символов до конца строки и добавьте этот (круглые скобки зафиксируют шаблон, так что «это» теперь$2
)в массив @ll
для печати.
А вот (уродливый )способ сделать это в awk:
$ awk '
(/ server\s*\{/){
if(out){
print out
}
out=""
}
($1=="listen" || $1=="root" || $1=="server_name"){
gsub(";","");
$1="";
gsub(/^ */,"");
out ? out=out" "$0 : out=$0
}
END{print out}' file
80 domain1.com www.domain1.com html
80 domain2.com www.domain2.com /var/www/virtual/big.server.com/htdocs
Всякий раз, когда у вас есть тег (, он же имя, он же ключ )для пар значений во входных данных, я считаю, что лучше всего сначала создать массив этого сопоставления(f[]
)ниже, а затем вы можете просто распечатать любые значения, которые вы хотите в любом порядке, в котором вы хотите, и в любых условиях, которые вы хотите, просто получая доступ к значениям массива по их тегам.
Например, используя любой POSIX awk:
$ cat tst.awk
(NR > 1) && ($1 == "server") { prt() }
{
tag = $1
sub(/[[:space:]]*[^[:space:]]+[[:space:]]+/,"")
sub(/;$/,"")
f[tag] = $0
}
END { prt() }
function prt() {
print f["listen"], f["server_name"], f["root"]
delete f
}
$ awk -f tst.awk file
80 domain1.com www.domain1.com html
80 domain2.com www.domain2.com /var/www/virtual/big.server.com/htdocs
Если вы застряли с awk, отличным от -POSIX, который не поддерживает классы символов, просто замените [:space:]
на \t
(это пустой символ, затем обратную косую черту, а затемt
).
Существуют более короткие способы просто получить вывод по вашему конкретному вопросу, но описанный выше подход дает вам возможность тривиально печатать, тестировать, переупорядочивать, изменять и т. д. эти и любые другие поля, с которыми вы хотите что-то делать.