저는 다양한 컴퓨터에서 미리 만들어진 실행 중인 프로세스 목록을 검색하는 스크립트를 작성하려고 합니다. 나는 특히 이러한 장치에서 실행 중인 rsyslogd를 찾고 그들이 사용하고 있는 구성 파일을 찾으려고 했습니다(기본 /etc/rsyslog.conf를 사용하지 않는 경우).
이제 다음 for 루프를 사용하여 컴퓨터를 성공적으로 검색하고 있습니다.
for root_file in $TARGET_DIR/RESULTS*/ps_results; do
grep rsyslogd $root_file | awk '{s = ""; for (i = 15; i <= NF; i++) s = s $i " "; print s}'
done
다음과 같은 목록이 반환됩니다.
# get_configs $TARGET_DIR/
/usr/sbin/rsyslogd -n
/sbin/rsyslogd -i /var/run/syslogd.pid -c 5
/usr/sbin/rsyslogd -n -f /usr/syslog.conf
...
하지만 내가 원하는 것은 확인 중인 컴퓨터의 IP 주소(스크립트의 RESULTS*에 있는 것처럼)와 그 뒤에 구성 파일의 경로를 보여주는 목록입니다. 다음과 같습니다.
# get_configs $TARGET_DIR/
172.16.10.1 /etc/syslog.conf
172.16.10.2 /etc/syslog.conf
172.17.5.245 /usr/syslog.conf
...
이 목록을 사용하여 파일을 구문 분석하고 지시문으로 연결될 수 있는 다른 구성 파일을 찾겠습니다 $IncludeConfig
. 하지만 먼저 파일 목록을 정리해야 합니다.
내가 겪고 있는 정신적 블록은 -f
rsyslogd 뒤의 옵션을 테스트하는 것입니다. rsyslogd에는 필요하지 않고 -f
기본 /etc/rsyslog.conf로 실행되므로 해당 옵션에 대한 테스트를 어떻게 처리하고 그 뒤에 있는 경로를 추출하거나 기본값을 제공할 수 있습니까?
sed
OR을 사용하여 "-f /path/to/file"을 분리하고 빈 결과에 /etc/rsyslog.conf를 반환하려고 생각했지만 cut
이를 달성할 수 없습니다.
답변1
다음과 같은 입력 파일이 있다고 가정합니다.
$ grep . */ps_results
RESULTS-172.16.10.1/ps_results:/usr/sbin/rsyslogd -n
RESULTS-172.16.10.2/ps_results:/sbin/rsyslogd -i /var/run/syslogd.pid -c 5
RESULTS-172.17.5.245/ps_results:/usr/sbin/rsyslogd -n -f /usr/syslog.conf
$
그래서 뭐?
$ awk '/rsyslogd/{gsub("^.*RESULTS-","",FILENAME);gsub("/ps_results","",FILENAME);b="/etc/rsyslog.conf";for(a=0;a++<NF;){if($a=="-f"){b=$(a+1)}};printf "%-15s%s\n",FILENAME,b}' RESULTS*/ps_results
172.16.10.1 /etc/rsyslog.conf
172.16.10.2 /etc/rsyslog.conf
172.17.5.245 /usr/syslog.conf
$
동일한 코드, 주석 + 서식:
awk '/rsyslogd/ {
# strip everything up to (and including) RESULTS- from the filename
gsub("^.*RESULTS-","",FILENAME)
# strip the /ps_results from the filename
gsub("/ps_results","",FILENAME)
# set the default rsyslog conf file
b="/etc/rsyslog.conf"
# look for a -f parameter: if found, grab conf file
for(a=0;a++<NF;){
if($a=="-f") {
b=$(a+1)
}
}
# print the ip addr and conf file
printf "%-15s%s\n",FILENAME,b
}' RESULTS*/ps_results
답변2
다음과 같이 기존 awk를 확장할 수 있습니다(이것은 고안된 독립 실행형 예입니다).
awk '{ s=$0;
if (match($s, / -f [^ ]+/)) {
print substr($s, RSTART+4, RLENGTH-4)
}
else
print "/etc/syslog.conf"
}' < input
문자열 $s
에 정규식 "(공백) -f(공백)(공백이 아닌 하나 이상의 문자)"가 포함되어 있는지 묻습니다. 그렇다면 정규식과 일치하는 하위 문자열을 4자만큼 오프셋하여 인쇄합니다(따라서 4만큼 단축됨). 문자) (공백) -f
(공백) 을 설명합니다 . 그렇다면$s
아니요기본 syslog.conf 경로를 인쇄하기 위한 위의 정규식을 포함합니다.
위의 코드는 기존 awk 스크립트의 끝에 배치되어 해당 print s
섹션을 대체합니다(물론 재할당하지 않고 s=$0
작업할 데이터가 있으므로 바로 거기에 있습니다).