아래에서 도움을 줄 수 있는지 확인하세요. 몇 가지 다른 방법을 시도했지만 원하는 것을 얻을 수 없습니다.
사용자ID.txt
user1
user2
user3
user4
user5
파일 1.txt
AmLogin server1 [03/Feb/2021:00:04:09 -0600] "11.11.11.11 uid=user1,ou=users,ou=company1,o=company"
AmLogin server1 [03/Feb/2021:00:05:11 -0600] "22.22.22.22 uid=user2,ou=users,ou=company1,o=company"
AmLogin server1 [03/Feb/2021:00:08:25 -0600] "33.33.33.33 uid=user3,ou=users,ou=company1,o=company"
파일 2.txt
AmLogin server2 [04/Feb/2021:00:01:09 -0600] "11.11.11.11 uid=user1,ou=users,ou=company1,o=company"
AmLogin server2 [04/Feb/2021:00:01:11 -0600] "22.22.22.22 uid=user2,ou=users,ou=company1,o=company"
AmLogin server2 [04/Feb/2021:00:01:25 -0600] "33.33.33.33 uid=user3,ou=users,ou=company1,o=company"
AmLogin server2 [04/Feb/2021:00:02:30 -0600] "11.11.11.11 uid=user1,ou=users,ou=company1,o=company"
AmLogin server2 [04/Feb/2021:00:05:20 -0600] "2.2.2.2 uid=user2,ou=people,dc=company2,dc=com"
AmLogin server5 [07/Feb/2021:00:02:30 -0600] "11.11.11.11 uid=user4,ou=People,ou=company1,o=company"
AmLogin server5 [08/Feb/2021:00:05:20 -0600] "2.2.2.2 uid=user5,ou=people,ou=employees,dc=company2,dc=com"
파일 3.txt
AmLogin server3 [05/Feb/2021:00:01:11 -0600] "22.22.22.22 uid=user2,ou=users,ou=company1,o=company"
AmLogin server3 [05/Feb/2021:00:01:25 -0600] "33.33.33.33 uid=user3,ou=users,ou=company1,o=company"
AmLogin server3 [05/Feb/2021:00:09:25 -0600] "33.33.33.33 uid=user3,ou=users,ou=company1,o=company"
AmLogin server3 [08/Dec/2020:00:11:44 -0600] "33.33.33.33 uid=user3,ou=users,ou=company1,o=company" "App1" [0002222000] [0] []
AmLogin server3 [09/Feb/2021:00:07:50 -0600] "33.33.33.33 uid=user3,ou=users,ou=company1,o=company" "App2" [0003455000] [0] []
다음 세부 정보를 사용하여 모든 사용자에 대한 최신 로그인 정보를 얻고 싶습니다. 위에 표시된 내용은 샘플 파일일 뿐입니다. 데이터를 추출해야 하는 100개의 거대한 로그 파일이 있습니다. 아래에서는 user2가 두 번 언급되며 사용자 ID가 동일한 것처럼 보이지만 서로 다른 DN(식별 이름)을 가진 두 명의 다른 사용자입니다. 고유 이름은 사용자의 전체 경로를 나타냅니다. user2의 예는 다음과 같습니다.ou=사용자,ou=회사1,o=회사다른 user2가 다음에 존재합니다.ou=사람,dc=회사2,dc=com. 아래 user4의 경우ou=직원,ou=회사1,o=회사user5의 경우 다음 위치에 있습니다.ou=직원,ou=직원,dc=company2,dc=com
큰따옴표 뒤의 끝 부분(user3)에 있는 일부 항목에는 무시할 수 있는 임의의 텍스트("App1"[0002222000][0][])가 포함되어 있습니다.
예상 출력.txt
user1|04/Feb/2021:00:02:30|uid=user1,ou=users,ou=company1,o=company
user2|05/Feb/2021:00:01:11|uid=user2,ou=users,ou=company1,o=company
user2|04/Feb/2021:00:05:20|uid=user2,ou=people,dc=company2,dc=com
user3|09/Feb/2021:00:07:50 -0600|uid=user3,ou=users,ou=company1,o=company
user4|07/Feb/2021:00:02:30|uid=user4,ou=People,ou=company1,o=company
user5|08/Feb/2021:00:05:20|uid=user5,ou=people,ou=employees,dc=company2,dc=com
아니면 시간이 없으면 더 쉬울 것입니다.
예상 출력.txt
user1|04/Feb/2021|uid=user1,ou=users,ou=company1,o=company
user2|05/Feb/2021|uid=user2,ou=users,ou=company1,o=company
user2|04/Feb/2021|uid=user2,ou=people,dc=company2,dc=com
user3|09/Feb/2021|uid=user3,ou=users,ou=company1,o=company
user4|07/Feb/2021|uid=user4,ou=People,ou=company1,o=company
user5|08/Feb/2021|uid=user5,ou=people,ou=employees,dc=company2,dc=com
usernames 를 사용하여 모든 파일을 greping하려고 시도했지만 $i
시간이 오래 걸립니다.
grep $i file*.txt | tail -1
답변1
#!/bin/sh
while read -r user
do
for group in users people
do
sed -nr "s/.*\[(\S+).*\s(uid=$user,ou=$group,.*)./$user|\1|\2/p" file*.txt | sort -t\| -k2.8nr -k2.4Mr -k2.1nr -k2.13,2.20r | grep -m1 "|uid=$user,ou=$group,"
done
done < userid.txt
편집하다:
로그 파일이 정렬되면 각 DN을 반복하고 tail -n1
첫 번째 패스에서는 사용자를 검색하고 userdn.txt
두 번째 패스에 대한 다른 입력 파일을 생성합니다.
#!/bin/sh
# list of users (from logs)
grep -Fiwhf userid.txt file*.txt | grep -io 'uid=[^"]*' | sort --ignore-case -u > userdn.txt
# last login
while read -r user
do
grep -Fiwh "$user" file*.txt | tail -n1 | sed -nr 's/.*\[(\S+).*\suid=([^,]+)(.*)./\2|\1|uid=\2\3/p'
done < userdn.txt
또는 프로세스 교체를 통해(bash에만 해당)
#!/bin/bash
while read -r user
do
grep -Fiwh "$user" file*.txt | tail -n1 | sed -nr 's/.*\[(\S+).*\suid=([^,]+)(.*)./\2|\1|uid=\2\3/p'
done < <(grep -Fiwhf userid.txt file*.txt | grep -io 'uid=[^"]*' | sort --ignore-case -u)
로그 파일이 정렬되지 않았고 디스크 공간보다 시간이 더 중요한 경우 3단계에 한 번만 정렬하여 시간을 절약하세요.
-create userdn.txt
- 로그 파일을 날짜별로 큰 단일 파일로 정렬 - 각 DN을
반복합니다 .bigfile.txt
#!/bin/sh
# list of users (from logs)
grep -Fiwhf userid.txt file*.txt | grep -io 'uid=[^"]*' | sort --ignore-case -u > userdn.txt
# merge log files
grep -Fiwhf userdn.txt file*.txt | sed -nr 's/.*\[(\S+).*\suid=([^,]+)(.*)./\2|\1|uid=\2\3/p' | sort -t\| -k2.8nr -k2.4Mr -k2.1nr -k2.13,2.20r > bigfile.txt
# last login
while read -r user
do
grep -Fiwm1 "$user" bigfile.txt
done < userdn.txt
각 로그는 각 사용자에 대해 여러 번 처리되기 때문에 이는 여전히 좋은 솔루션이 아닙니다. 다른 해결책 awk
이나 join
뭔가 paste
가 있어야 합니다 uniq
.
이상적으로는 결합할 것입니다...
tac file*.txt | grep -m1 -f userdn.txt
...그러나 이는 두 가지 이유로 작동하지 않습니다.
tac
예상대로 작동하는 대신 각 로그가 순차적으로 처리됩니다. 검색하지
-m1
않고 결합-f
모두모드(파일에서), 그러나 그 이후에는 중지됩니다.어느무늬.
하지만 이는 이미 정렬된 로그에만 적용됩니다. :(
원하는 것은 로그 파일을 단일 패스로 처리하여 각 줄을 읽고 결과를 다른 파일에 쓰는 것입니다. 여기서 쓰기 이벤트는 함수를 통해 구현됩니다.
이 기능은 다음을 수행해야 합니다.
- DN이 이미 존재하는지 확인
- 날짜 비교
- 기존 항목 업데이트
- 새 항목만 추가
#!/bin/bash
shopt -s extglob
# function compare date
compare () {
[ -n "$2" ] || return 1
# sort array
for date in "$@"
do
echo "$date"
done | sort -k1.8n -k1.4M -k1.1n -k1.13,1.20 | tail -n1
return 0
}
# function write last_login.txt
update () {
local file=$1 line=$2
[ -n "$line" ] || return 1
# string manipulation
dn=${line#*\"}; dn=${dn%%\"*}; dn=${dn#*+([[:blank:]])}; [ -n "$dn" ] || return 1
user=${dn%%,*}; user=${user#*=};
date2=${line#*[}; date2=${date2%%]*}; date2=${date2%+([[:blank:]])*};
[ -f "$file" ] && date1=$(grep -Fiwm1 "$dn" "$file" | cut -d\| -f2)
if [ -n "$date1" ]
then
# DN already exist
[ "$date1" = "$date2" ] && return 0
date=$(compare "$date1" "$date2")
if [ "$date" != "$date1" ]
then
# update existing entry
sed -i "s;$user|$date1|$dn;$user|$date2|$dn;i" "$file"
fi
else
# add new entries only
echo "$user|$date2|$dn" >> "$file"
fi
return 0
}
# create last_login.txt
for file in file*.txt
do
[ -f "$file" ] || continue
echo "processing $file"
while read -r line
do
update last_login.txt "${line//;/,}"
done < <(tac "$file")
done
# sort last_login.txt
echo -n "sorting... "
sort -o last_login.txt last_login.txt
echo "finished"
exit 0