쉘스크립트 기본 참고 사이트 : shell script 기본
1. for 문 활용
1) 특정 디렉토리내의 파일들의 내용을 보기
[root@RHEL63-1 ~]# for i in `ls /sys/class/iscsi_host/*/ipaddress`; do echo $i; cat $i; done /sys/class/iscsi_host/host3/ipaddress 192.168.2.175 /sys/class/iscsi_host/host4/ipaddress 192.168.0.175 /sys/class/iscsi_host/host5/ipaddress 192.168.0.175 /sys/class/iscsi_host/host6/ipaddress 192.168.2.175
- iscsi host* 들에 대한 ipaddress 를 모두 보여주는 것이다.
- 아래와 같이 표현해도 된다.
#!/bin/bash for i in `ls /sys/class/iscsi_host/*/ipaddress`; do echo $i cat $i done
또는
[root@server ~]# cat /sys/class/scsi_host/host*/device/scsi_host/host*/state running running running [root@server ~]# find /sys/class/scsi_host/host*/device/scsi_host/host*/state -exec grep -H . {} \; /sys/class/scsi_host/host0/device/scsi_host/host0/state:running /sys/class/scsi_host/host1/device/scsi_host/host1/state:running /sys/class/scsi_host/host2/device/scsi_host/host2/state:running [root@server ~]# find /sys/class/scsi_host/host*/device/scsi_host/host*/state| xargs grep -H . /sys/class/scsi_host/host0/device/scsi_host/host0/state:running /sys/class/scsi_host/host1/device/scsi_host/host1/state:running /sys/class/scsi_host/host2/device/scsi_host/host2/state:running
2) NIC 링크 상태 간략하게 뽑아보기
for LIST in `ifconfig -a | grep eth | awk '{print $1}'`; do echo "${LIST} - `ethtool ${LIST} | grep 'Link detected'`"; done eth0 - Link detected: yes eth1 - Link detected: yes eth2 - Link detected: yes eth3 - Link detected: no eth4 - Link detected: no eth5 - Link detected: yes
3) rm 문자를 포함하는 TEXT 파일 검출
시스템에 있는 모든 TEXT 파일의 내용을 뒤져서 rm 명령어가 포함되어 있는지를 확인, 포함하고 있는 파일은 화면에 출력한다.
#!/bin/bash BEGIN_PATH=/ function check_rm() { if [ -r $i ]; then for cmd in "/bin/rm\ " "/rm\ " "^rm\ " "\ rm\ "; do if grep -q "$cmd" $1; then echo $1; fi done fi } for d in $(ls $BEGIN_PATH); do if [ $BEGIN_PATH == '/' ]; then local_path="/$d"; else local_path="$BEGIN_PATH/$d"; fi if [ -d $local_path ]; then for i in $(find $local_path -exec file {} \; | grep text | egrep -v "RPM|x86_64" | cut -d: -f1); do check_rm "$i" done elif [ -f $local_path ]; then for i in $(find $local_path -exec file {} \; | grep text | egrep -v "RPM|x86_64" | cut -d: -f1); do check_rm $local_path done fi done
- rpm 파일은 rm 문자를 포함하는 검사에서 제외하고 진행한다.
4) 불필요한 LSB(Linux Standard Base) User에 대한 주석처리
프로젝트상 보안 스크립를 돌리면 아래 계정에 대한 보안 취약점이 존재한다고 할때가 있다.
이때 아래와 같은 스크립트를 적용하면 쉽게 해당 계정을 주석처리하여 workaround 할 수 있다.
#!/bin/bash CREATE_FILE=`hostname`"_linux_"`date +%m%d`.txt applyuser=`cat /etc/passwd | egrep "^ftp|^uucp|^lp|^sync|^halt|^shutdown|^games|^daemon|^bin|^sys|^adm|^newes|^gopher"|awk -F : '{print $1}'` >> $CREATE_FILE 2>&1 for i in $applyuser do #cat $CREATE_FILE |grep "1.01 결과 : 취약" #if [ $? == "0" ] ; then find /etc/passwd -exec perl -pi -e 's/^'$i'/#'$i'/g' {} \; > /dev/null 2>&1 echo $i >> $CREATE_FILE 2>&1 #fi done
* 위 코드의 주석 부분을 해제 후 보안 스크립트 내에 삽입하면 보안 스크립트를 돌릴때 바로 적용할 수 있다.
또한 아래와 같은 코드로 수행을 시켜도 적용 가능하다.
#!/bin/bash array_name=("ftp" "uucp" "lp" "sync" "halt" "shutdown" "games" "daemon" "bin" "sys" "adm" "news" "gopher") for (( i = 0 ; i < ${#array_name[@]} ; i++ )) ; do #sed -i '/^'${array_name[$i]}'/s/'^${array_name[$i]}'/#'${array_name[$i]}'/g' /root/passwd sed -i 's/^'${array_name[$i]}'/#'${array_name[$i]}'/g' /root/passwd echo "${array_name[$i]}" user change to "#${array_name[$i]}" done
5) 메모리 사용량 보기
아래 스크립트를 아래처럼 watch와 조합하여 실행하면 실시간 메모리 사용량 체크가 가능하다.
# watch -d -n1 memusage.sh
#!/bin/bash echo "####################### USAGE REAL MEMOMRY PER USER #########################" LIST_FILE=`ps -eo user,pid,rss,comm --sort -rss | awk '$3 > 0 {print $1}' | sort -u | grep -v "USER"` TOTAL_SUM=0 for LIST in ${LIST_FILE}; do PROC_COUNT=`ps -eo user,pid,rss,comm --sort -rss | awk '$3 > 0 && $1 ~ /^'"${LIST}"'$/ {print $0}' | wc -l` MEM_LIST=`ps -eo user,pid,rss,comm --sort -rss | awk '$3 > 0 && $1 ~ /^'"${LIST}"'$/ {print $3}'` MEMSUM=0 for M_LIST in ${MEM_LIST}; do MEMSUM=`expr ${MEMSUM} + ${M_LIST}` done TOTAL_SUM=`expr ${TOTAL_SUM} + ${MEMSUM}` echo -e "[USER=${LIST}]\t\t[Process=${PROC_COUNT}]\t\t[Real Mem=${MEMSUM} KByte]" done echo TOTAL=$(echo "(" ${TOTAL_SUM}") / 1024" | bc) echo "Total Use Real Memory = $TOTAL MB" echo "#############################################################################" echo echo "############################## DISK CACHE USAGE #############################" BUF=$(echo "(" $(cat /proc/meminfo | grep -e Buffers -e '^Cached' | awk '{print $2}' | paste -s -d "+") ") /1024" | bc) | paste -s -d "+" | bc) ACT=$(echo "(" $(cat /proc/meminfo | grep -e 'Active(file)' -e 'Inactive(file)' -e Shmem | awk '{print $2}' | paste -s -d "+") ") / 1024" | bc) echo "Buffers + Cached = "$BUF" MB" echo "Active(file) + Inactive(file) + Shmem = "$ACT" MB" echo "#############################################################################"
6) 파일의 내용을 라인별로 읽어서 2개의 컬럼 데이터를 동시에 출력
# cat list.txt 192.168.1.82 645d161c-33c1-7e7b-0657-832cb3ff2a91 192.168.1.83 645d161c-33c1-7e7b-0657-832cb3ff2a92 192.168.1.84 645d161c-33c1-7e7b-0657-832cb3ff2a93
스크립트 방법 1)
중첩 for문 활용
#!/bin/bash SSH_OPTION="-o ConnectTimeout=3 -o StrictHostKeyChecking=no" NODE=$(awk -F'\t' '{print $1}' list.txt) UUID=$(awk -F'\t' '{print $2}' list.txt) c=0 for i in $NODE do for j in $i do ARR=($UUID) echo $j echo ${ARR[c]}; #sshpass -p "##" ssh -q $SSH_OPTION root@$j "xe vm-shutdown --force uuid=${ARR[c]}" & c=$((c+1)) done done
--> 두번째 for문에서 ARR array에 두번째 컬럼 값을 넣고 array 0번부터 출력. 여기서는 3줄만 있으므로 0 ~ 2 까지 두번째 for loop가 돌면서
방법 2)
while read 문 활용
#!/bin/bash SSH_OPTION="-o ConnectTimeout=3 -o StrictHostKeyChecking=no" while read line do NODE=$(echo $line | awk -F' ' '{print $1}') UUID=$(echo $line | awk -F' ' '{print $2}') echo "$NODE" echo "$UUID" #sshpass -p "##" ssh -q $SSH_OPTION root@$NODE "xe vm-shutdown --force uuid=$UUID" & done < list.txt |
결과 (결과는 방법 1, 2 모두 동일)
# ./test.sh 192.168.1.82 645d161c-33c1-7e7b-0657-832cb3ff2a91 192.168.1.83 645d161c-33c1-7e7b-0657-832cb3ff2a92 192.168.1.84 645d161c-33c1-7e7b-0657-832cb3ff2a93
만약 for 문에서 단순 중첩 for문을 이용하면 아래처럼 출력이 된다.
# ./test.sh
192.168.1.82
645d161c-33c1-7e7b-0657-832cb3ff2a91
645d161c-33c1-7e7b-0657-832cb3ff2a92
645d161c-33c1-7e7b-0657-832cb3ff2a93
192.168.1.83
645d161c-33c1-7e7b-0657-832cb3ff2a91
645d161c-33c1-7e7b-0657-832cb3ff2a92
645d161c-33c1-7e7b-0657-832cb3ff2a93
192.168.1.84
645d161c-33c1-7e7b-0657-832cb3ff2a91
645d161c-33c1-7e7b-0657-832cb3ff2a92
645d161c-33c1-7e7b-0657-832cb3ff2a93
즉, 아래처럼 단순히 두번째 for문을 작성하면 두번째 컬럼이 위와 같이 한번에 모두 출력이 됨.
for i in $NODE do echo $i for j in $UUID do echo $j done done 또는 for i in $NODE do echo $i ARR=($UUID) for (( j=0; j<${#ARR[@]}; j++ )); do echo ${ARR[j]} done done |
[ 참조 ]
2. while 문 활용
1) 특정 디렉토리 내의 파일 및 디렉토리 리스트 보기
[root@RHEL63-1 ~]# while :;do ls -la /tmp; sleep 1; clear; done; total 1230484 drwxrwxrwt. 4 root root 4096 Aug 26 03:32 . dr-xr-xr-x. 29 root root 4096 Aug 22 13:46 .. -rwx------. 1 root root 2361 Aug 16 15:35 dropcacherun.sh_2016081601 drwxrwxrwt 2 root root 4096 Aug 18 13:22 .ICE-unix -rw-r--r--. 1 root root 3481 Aug 17 10:30 mcetrace.log srwxrwxrwx 1 dbadm dba 0 Aug 24 10:55 mysql.sock drwxr-xr-x. 2 root root 4096 Aug 17 18:28 suds -rw------- 1 root root 155849 Aug 18 19:09 tmpDpnySm -rw------- 1 root root 155849 Aug 18 19:09 tmpSwf3ya -rw------- 1 root root 155849 Aug 18 19:10 tmpTEzfkR -rw------- 1 root root 155849 Aug 18 19:09 tmpz17srj
- /tmp 디렉토리를 1초 단위로 reflesh 하면서 출력해 준다.
- 아래와 같이 표현해도 된다.
#!/bin/bash while :; do ls -la /tmp sleep 1 clear done
또는 watch를 이용해서 간단하게 실행할 수도 있다.
[root@RHEL63-1 ~]# watch -d -n1 'ls -la /tmp'
2) 10초간만 /tmp 디렉토리의 파일/디렉토리를 리스트업 하고 끝낸다.
#!/bin/bash num=10 while [ $num -ge 1 ]; do ls -la /tmp sleep 1 clear num=$((num-1)) done
3) 어떠한(여기서는 crsctl) 상태를 3초에 한번씩 date를 찍으며 계속 모니터링 하기.
# while true do echo "###########" date crsctl stat res -t sleep 3 done
- 아래와 같이 한줄로 표현할 수도 있다.
# while true :; do echo "###########" ; date; crsctl stat res -t; sleep 3; done
4) TCPBacklogDrop 값을 확인
# cat /proc/net/netstat | awk '(f==0) {name=$1; i=2; while ( i<=NF) {n[i] = $i; i++ }; f=1; next} (f==1){ i=2; while ( i<=NF){ printf "%s%s = %d\n", name, n[i], $i; i++}; f=0} ' | grep TCPBacklogDrop
* 만약 전체 내용을 확인 하고자 하면 맨 뒤의 grep TCPBacklogDrop을 제거한다.
5) 모든 프로세스의 RSS 값(메모리 사용량) 합산해서 보기
# while :; do clear; echo "(" $(ps -eo rss | egrep -v ' 0' | egrep -v RSS | paste -s -d "+") ") / 1024" | bc ; sleep 1 ; done
6) tmpfs (/dev/shm) 메모리 파일시스템에 랜덤한 파일 생성하기
# while :; do RNUM=$(shuf -i 1-10000 -n 1); dd if=/dev/zero of=/dev/shm/file.`echo $RNUM` count=1 bs=10M status=progress ; echo "created file: /dev/shm/file.$RNUM" ; sleep 1 ; clear ; done 1+0 records in 1+0 records out 10485760 bytes (10 MB) copied, 0.00659528 s, 1.6 GB/s created file: /dev/shm/file.8329
* /dev/shm에 file.XXXX 이름의 10MB 용량의 파일이 1초 단위로 용량이 full이 될 때까지 생성된다.
* dd 버전이 낮으면 'status=progress' 옵션이 없을 수 있다. 그럴 경우 이 옵션은 제외하고 실행.
수행 후 아래와 같이 메모리 캐시 및 스왑 정리
# sync # echo 3 > /proc/sys/vm/drop_caches # echo 0 > /proc/sys/vm/drop_caches # swapoff -a # swapon -a
* 수행 전 프로세스 메모리 상태를 보고 수행할 것.
- 만약 /dev/shm의 RHEL 기본 사이즈인 메모리의 50%에서 95%로 조정하고 싶다면 아래와 같이 수행
# mount -o defaults,size=$(free -m | grep Mem | awk '{printf "%.0f",$2 * 95 / 100}')m,remount /dev/shm
- dialog와 dd 연동
(pv -n /dev/sda | dd of=/dev/sdb bs=128M conv=notrunc,noerror) 2>&1 | dialog --gauge "Running dd command (cloning), please wait…" 10 70 0
3. AWK, grep, sed, cut 활용
1) AWK를 활용하여 디스크들의 총합을 구하는 것이다.
[root@RHEL63-1 ~]# cat /proc/partitions | grep sd* | egrep -v [1-9]$ major minor #blocks name 8 0 33554432 sda 8 16 52428800 sdb 8 32 52428800 sdc 8 48 52428800 sdd 8 64 52428800 sde 8 80 26214400 sdf 8 96 26214400 sdg 8 112 26214400 sdh 8 128 26214400 sdi [root@RHEL63-1 ~]# cat /proc/partitions | grep sd* | egrep -v [1-9]$ | awk '{ SUM+=$3 } END { print SUM/1024/1024 " GB" }' 332 GB
- SUM+=$3 마치 while 문처럼 동작을 한다. $3 필드값을 모두 더한다.
- 총합이 332GB 이다.
2) grep 활용
- 파티션 정보 중 공백을 기준으로 네번째 필드만 출력
[root@RHEL63-1 ~]# cat /proc/partitions | awk '{ print $4 }' name loop0 sda sda1 sda2 dm-0 dm-1 sdb sdc dm-2 dm-3 sdd sde dm-5 dm-4 sdf sdg dm-6 dm-7 sdh sdi dm-8
- 네번째 필드에서 맨앞 문자가 d 또는 s로 시작하는 값들만 출력
[root@RHEL63-1 ~]# cat /proc/partitions | awk '{ print $4 }' | grep ^[ds] sda sda1 sda2 dm-0 dm-1 sdb sdc dm-2 dm-3 sdd sde dm-5 dm-4 sdf sdg dm-6 dm-7 sdh sdi dm-8
- grep과 정규표현식을 이용하여 8자리 단위로 쪼개서 배열에 넣고 출력하기.
# array_name[1]=$(echo b5f1e7bfc2439c621353d1ce0629fb8b | grep -o '[a-f0-9]\{8\}') # echo ${array_name[1]} b5f1e7bf c2439c62 1353d1ce 0629fb8b # echo ${array_name[@]} b5f1e7bf c2439c62 1353d1ce 0629fb8b # array_name[2]=$(echo b5f1e7bfc2439c621353d1ce0629fb8b | grep -o '[a-f0-9]\{8\}') # echo ${array_name[2]} b5f1e7bf c2439c62 1353d1ce 0629fb8b # echo ${array_name[@]} b5f1e7bf c2439c62 1353d1ce 0629fb8b b5f1e7bf c2439c62 1353d1ce 0629fb8b # array_name[3]=$(echo b5f1e7bfc2439c621353d1ce0629fb8b | grep -o '[a-f0-9]\{8\}') # echo ${array_name[3]} b5f1e7bf c2439c62 1353d1ce 0629fb8b # echo ${array_name[@]} --> #print array_name all item b5f1e7bf c2439c62 1353d1ce 0629fb8b b5f1e7bf c2439c62 1353d1ce 0629fb8b b5f1e7bf c2439c62 1353d1ce 0629fb8b # echo ${array_name[*]} --> #print array_name all item b5f1e7bf c2439c62 1353d1ce 0629fb8b b5f1e7bf c2439c62 1353d1ce 0629fb8b b5f1e7bf c2439c62 1353d1ce 0629fb8b # echo ${!array_name[@]} --> #print array_name index number 1 2 3 # echo ${#array_name[@]} --> #print array_name size 3
또는
# array_name=( $(echo b5f1e7bfc2439c621353d1ce0629fb8b | grep -o '[a-f0-9]\{8\}') ) # echo ${array_name[@]} b5f1e7bf c2439c62 1353d1ce 0629fb8b
3) messages 로그 파일 특정 시간 단위만 출력 하기
- messages 로그들 중 2월 22일, 24일 날짜의 15시 00분 00초 ~ 18시 20분 00초 사이의 로그만 출력
# cat /var/log/messages* | awk '$3 >= "15:00:00" && $3 <= "18:20:00"' | grep -e "Feb 22" -e "Feb 24"
- messages 로그들 중 2월 2일 날짜만 제외하고 15시 00분 00초 ~ 18시 20분 00초 사이의 로그만 출력
# cat /var/log/messages* | awk '$3 >= "15:00:00" && $3 <= "18:20:00"' | grep -v "Feb 2"
4) 리눅스 유저 계정 생성일 확인하기
- gnome 이 설치되어 있는데 RunLevel 3로 운영한 시스템의 사용자 계정 생성일을 찾는 스크립트 임.
# find $(awk -F: '{if ($3 >= 999) { print $(NF-1) } }' /etc/passwd | grep -v 'lib/nfs') -maxdepth 3 -type d -name '.mozilla' | xargs ls -Alct --full-time | grep plugins | awk -F " " '{ print $3 " " $4 " " $6 }'
서버에 따라 이 방법으로 찾을 수 없을 수도 있다. 참고만 할 것.
계정 생성 후 도중에 계정 비번을 변경하는 등.. 세월이 많이 흐른 뒤 서버의 계정들의 최초 생성일을 정확히 알 방법이 딱히 없다. 혹시 아는분은 답글로 남겨주시길..
5) grub.conf의 UUID 수정
ASIS : RHEL 6.2 on HP DL380 G8 (G8 기종 EOS)
TOBE : RHEL 6.8 on HP DL380 G9
HP가 Certification을 하지 않기 때문에 G8의 6.2 OS HDD를 DL380 G9으로 옮긴 후 Upgrade를 하지 못하는 상황. 따라서 G9에 RHEL 6.8을 신규 설치 후 마이그레이션 진행함.
RHEL 6.2 -> RHEL 6.8 으로 마이그레이션 과정 중 기존 환경파일 grub.conf를 그대로 복사 후 root=UUID를 sed 변경하는.. RHEL 6.8에서 아래와 같이 수행한다.
LVM을 사용하지 않았을 경우에만 해당된다. 그리고 root 파티션 /dev/sda1 는 환경에 맞게 변경.
아래 3가지 방법 모두 동일한 결과가 반영됨. [root@RHEL68 ~]# sed -i 's/root=UUID=[a-zA-Z|0-9|\-]*/root\=UUID='$(tune2fs -l /dev/sda1 | grep UUID | awk '{print $3}')'/g' /boot/grub/grub.conf [root@RHEL68 ~]# sed -i 's/root=UUID=?*[a-zA-Z|0-9|\-]*/root\=UUID='$(tune2fs -l /dev/sda1 | grep UUID | awk '{print $3}')'/g' /boot/grub/grub.conf [root@RHEL68 ~]# sed -i 's/root=UUID=?*...................................../root\=UUID='$(tune2fs -l /dev/sda1 | grep UUID | awk '{print $3}')'\ /g' /boot/grub/grub.conf
6) sed 대소문자 치환
원래 파일 내용 [root@localhost ~]# cat aa.txt 123abC EOerJL 대문자를 모두 소문자(Lower Case)로 변경 [root@localhost ~]# sed 's/.*/\L&/' aa.txt 123abc eoerjl 소문자를 모두 대문자(Upper Case)로 변경 [root@localhost ~]# sed 's/.*/\U&/' aa.txt 123ABC EOERJL
7) fuser 결과값 파일로 저장
명령행에서는 아래처럼 출력이 되지만 [root@localhost ~]# /sbin/fuser -cu /tmp /tmp: 1rce(root) 2rc(root) 3rc(root) 4rc(root) 5rc(root) 6rc(root) 7rc(root) 8rc(root) 9rc(root) 10rc(root) 11rc(root) 12rc(root) 13rc(root) 14rc(root) 15rc(root) 16rc(root) 17rc(root) 18rc(root) 19rc(root) 20rc(root) 21rc(root) 22rc(root) 23rc(root) 24rc(root) 25rc(root) 26rc(root) 27rc(root) 28rc(root) 29rc(root) 30rc(root) 31rc(root) 32rc(root) 33rc(root) 34rc(root) 35rc(root) 36rc(root) 37rc(root) 38rc(root) 39rc(root) 40rc(root) 41rc(root) 42rc(root) 43rc(root) 45rc(root) 46rc(root) 47rc(root) 48rc(root) 49rc(root) 50rc(root) 51rc(root) 52rc(root) 59rc(root) 60rc(root) 61rc(root) 63rc(root) 64rc(root) 65rc(root) 97rc(root) 98rc(root) 289rc(root) 290rc(root) 302rc(root) 303rc(root) 438rc(root) 439rc(root) 537rce(root) 773rc(root) 1193rc(root) 1194rc(root) 1195rc(root) 1196rc(root) 1232rc(root) 1417rce(root) 1477rce(root) 1499rce(rpc) 1512rce(dbus) 1633rce(root) 1661rce(root) 1673rce(root) 1789rce(root) 1796rce(root) 1798rce(root) 1800rce(root) 1802rce(root) 1804rce(root) 1806rce(root) 1811rce(root) 1812rce(root) 1855rce(root) 1856rce(root) 1866rce(root) 1869rc(root) 1928rce(root) 2368rce(root) 5420rce(root) 5422rc(root) 5423rce(root) 11499rce(root) 29271rce(apache) 29272rce(apache) 29273rce(apache) 29274rce(apache) 29275rce(apache) 29277rce(apache) 29278rce(apache) 29279rce(apache) 화면 출력을 파일로 redirect 하면 제대로 출력이 되지 않는다. [root@localhost ~]# /sbin/fuser -fcu /tmp > /root/resultfuser.txt /tmp: rce(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rce(root)rc(root)rc(root)rc(root)rc(root)rc(root)rc(root)rce(root)rce(root)rce(rpc)rce(dbus)rce(root)rce(root)rce(root)rce(root)rce(root)rce(root)rce(root)rce(root)rce(root)rce(root)rce(root)rce(root)rce(root)rce(root)rce(root)rc(root)rce(root)rce(root)rce(root)rce(root)rce(root)rce(apache)rce(apache)rce(apache)rce(apache)rce(apache)rce(apache)rce(apache)rce(apache) [root@localhost ~]# cat /root/resultfuser.txt 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 45 46 47 48 49 50 51 52 59 60 61 63 64 65 97 98 289 290 302 303 438 439 537 773 1193 1194 1195 1196 1232 1417 1477 1499 1512 1633 1661 1673 1789 1796 1798 1800 1802 1804 1806 1811 1812 1855 1856 1866 1869 1928 2368 5420 5423 11499 29271 29272 29273 29274 29275 29277 29278 29279 아래와 같이 표준에러를 표준출력(2>&1)으로 redirection 하면 원하는 결과값을 파일로 저장할 수 있다. [root@localhost ~]# /sbin/fuser -fcu /tmp > /root/resultfuser.txt 2>&1 [root@localhost ~]# cat /root/resultfuser.txt /tmp: 1rce(root) 2rc(root) 3rc(root) 4rc(root) 5rc(root) 6rc(root) 7rc(root) 8rc(root) 9rc(root) 10rc(root) 11rc(root) 12rc(root) 13rc(root) 14rc(root) 15rc(root) 16rc(root) 17rc(root) 18rc(root) 19rc(root) 20rc(root) 21rc(root) 22rc(root) 23rc(root) 24rc(root) 25rc(root) 26rc(root) 27rc(root) 28rc(root) 29rc(root) 30rc(root) 31rc(root) 32rc(root) 33rc(root) 34rc(root) 35rc(root) 36rc(root) 37rc(root) 38rc(root) 39rc(root) 40rc(root) 41rc(root) 42rc(root) 43rc(root) 45rc(root) 46rc(root) 47rc(root) 48rc(root) 49rc(root) 50rc(root) 51rc(root) 52rc(root) 59rc(root) 60rc(root) 61rc(root) 63rc(root) 64rc(root) 65rc(root) 97rc(root) 98rc(root) 289rc(root) 290rc(root) 302rc(root) 303rc(root) 438rc(root) 439rc(root) 537rce(root) 773rc(root) 1193rc(root) 1194rc(root) 1195rc(root) 1196rc(root) 1232rc(root) 1417rce(root) 1477rce(root) 1499rce(rpc) 1512rce(dbus) 1633rce(root) 1661rce(root) 1673rce(root) 1789rce(root) 1796rce(root) 1798rce(root) 1800rce(root) 1802rce(root) 1804rce(root) 1806rce(root) 1811rce(root) 1812rce(root) 1855rce(root) 1856rce(root) 1866rce(root) 1869rc(root) 1928rce(root) 2368rce(root) 5420rce(root) 5423rce(root) 5481rc(root) 11499rce(root) 29271rce(apache) 29272rce(apache) 29273rce(apache) 29274rce(apache) 29275rce(apache) 29277rce(apache) 29278rce(apache) 29279rce(apache)
8) netstat 로컬 ip address 의 특정 포트 영역 사용 중 확인
[root@testserver ~]# netstat -na | awk -F'[[:space:]]+|:' 'NR>2 && $5>=12000 && $5<=12900'
12000 ~ 12900 범위의 현재 사용중인 포트 출력
9) 특정 라인 주석 제거 및 삽입
- 주석 제거
# sed -ri 's/^#(.*sufficient\s+pam_wheel\.so trust use_uid.*)/\1/' /etc/pam.d/su #auth sufficient pam_wheel.so trust use_uid (위 라인의 주석이 제거됨)
-> sed의 -r 옵션을 통해 regular expression을 활성화하여 좀 더 디테일하게 문자를 다룬다.
- 주석 삽입
# sed -ri 's/(.*sufficient\s+pam_wheel\.so trust use_uid.*)/#\1/' /etc/pam.d/su
- 주석 삽입(이중 주석 방지)
하지만 주석이 이미 있는 경우 위와 같이 주석을 삽입하게 되면 주석이 또 삽입된다.
아래와 같이 주석이 없는 라인만을 대상으로 해당 필터된 라인에 대해 주석을 넣는 방식을 사용하면 이중 주석의 문제가 해결된다.
# sed -ri '/(^#)/! s/(.*sufficient\s+pam_wheel\.so trust use_uid.*)/#\1/' /etc/pam.d/su
-> 라인의 첫번째 문자가 #으로 시작하지 않는 라인에 대해서만 해당 필터 문구에 대해서 주석을 넣겠다는 의미.
- 각 기호에 대한 설명
s/ # Substitute ^# # A line starting with a # ( # Start capture group .* # Followed by anything sufficient # Followed by the word sufficient \s+ # Followed by whitespace pam_wheel\.so trust use_uid # Followed by the literal string (escaped .) .* # Followed by anything ) # Stop capture group / # Replace with \1 # The first capture group
10) for 문을 이용한 여러개의 도메인에 순차적으로 한번에 icmp 패킷 전송 (ping)
# for i in nodea.{cluster1,private,storage{1,2}}.example.com; do > ping -c 1 ${i} > done
위와 같이 수행시 아래 도메인으로 ping
nodea.cluster1.example.com
nodea.private.example.com
nodea.storage1.example.com
nodea.storage2.example.com
11) APNIC ip 대역 리스트에서 국가별 총 IP 갯수를 도출하기
2번째(국가), 5번째(ip 갯수)를 출력하고 국가별로 총합을 구한 리스트를 만들기
아래 URL에서 원본 파일을 다운받을 수 있다
https://ftp.apnic.net/stats/apnic/delegated-apnic-extended-latest
[root@pyhost ~]# cat delegated-*
2.3|apnic|20200912|134221||20200911|+1000
apnic|*|asn|*|10837|summary
apnic|*|ipv4|*|46677|summary
apnic|*|ipv6|*|76707|summary
apnic|AU|ipv4|1.0.0.0|256|20110811|assigned|A91872ED
apnic|CN|ipv4|1.0.1.0|256|20110414|allocated|A92E1062
apnic|CN|ipv4|1.0.2.0|512|20110414|allocated|A92E1062
apnic|AU|ipv4|1.0.4.0|1024|20110412|allocated|A9192210
apnic|CN|ipv4|1.0.8.0|2048|20110412|allocated|A92319D5
apnic|JP|ipv4|1.0.16.0|4096|20110412|allocated|A92D9378
apnic|CN|ipv4|1.0.32.0|8192|20110412|allocated|A92319D5
apnic|JP|ipv4|1.0.64.0|16384|20110412|allocated|A9252414
apnic|TH|ipv4|1.0.128.0|32768|20110408|allocated|A91CF4FE
apnic|CN|ipv4|1.1.0.0|256|20110414|allocated|A92E1062
apnic|AU|ipv4|1.1.1.0|256|20110811|assigned|A91872ED
apnic|CN|ipv4|1.1.2.0|512|20110414|allocated|A92E1062
apnic|CN|ipv4|1.1.4.0|1024|20110414|allocated|A92E1062
apnic|CN|ipv4|1.1.8.0|256|20110412|allocated|A91E9A58
apnic|CN|ipv4|1.1.9.0|256|20110412|allocated|A92319D5
apnic|CN|ipv4|1.1.10.0|512|20110412|allocated|A92319D5
apnic|CN|ipv4|1.1.12.0|1024|20110412|allocated|A92319D5
apnic|CN|ipv4|1.1.16.0|4096|20110412|allocated|A92319D5
apnic|CN|ipv4|1.1.32.0|8192|20110412|allocated|A92319D5
apnic|JP|ipv4|1.1.64.0|16384|20110412|allocated|A92D9378
apnic|TH|ipv4|1.1.128.0|32768|20110408|allocated|A91CF4FE
apnic|CN|ipv4|1.2.0.0|512|20110414|allocated|A92E1062
apnic|CN|ipv4|1.2.2.0|256|20110331|assigned|A9272682
~~ snip ~~
[root@pyhost ~]# cat delegated-* | grep -v summary | awk -F"|" '$3=="ipv4" && $2!="" {print $2, $5}' | sort | awk '{x[$1]+=$2} END { for (i in x) print i "\t" x[i] }' | sort -nrk2
CN 340707584
JP 190012928
KR 112455424
AU 54872064
IN 41104640
TW 35703552
SG 22695936
~~ snip ~~
특정 변수가 숫자인지 아닌지 판별하기
MYVAL=2A
RE='^[0-9]+$'
if ! [[ $MYVAL =~ $RE ]] ; then
echo "$MYVAL is not a number" >&2;
else
echo "$MYVAL is a number"
fi
특정 파일의 라인별 값을 따옴표로 묶고 쉼표로 구분해서 일렬로 출력하기
[root@ex342 ~]# cat aa.txt
24796
7827
23982
2309
54984
[root@ex342 ~]# echo `awk '{ print "\""$0"\"" }' aa.txt` | sed "s/ /, /g;s/\"/\'/g"
'24796', '7827', '23982', '2309', '54984'
[root@ex342 ~]# echo `awk '{ print "'\''"$0"'\''" }' aa.txt` | sed "s/ /, /g"
'24796', '7827', '23982', '2309', '54984'
[root@ex342 ~]# echo `awk '{ print "\047"$0"\047" }' aa.txt` | sed 's/ /, /g'
'24796', '7827', '23982', '2309', '54984'
crontab의 특정 패턴(단어)이 포함된 라인만 삭제
[root@cent77 test]# crontab -l
* * * * * echo "hello world"
* * * * * echo "hi world"
* * * * * echo "yes world"
[root@cent77 test]# crontab -l | grep -v "hello" | crontab -
[root@cent77 test]# crontab -l
* * * * * echo "hi world"
crontab의 특정 패턴(단어)이 포함된 라인만 제외하고 모두 삭제
[root@cent77 test]# crontab -l
* * * * * echo "hello world"
* * * * * echo "hi world"
* * * * * echo "yes world"
[root@cent77 test]# crontab -l | grep "hello" | crontab -
[root@cent77 test]# crontab -l
* * * * * echo "hello world"
grep 활용
[student@workstation ~]$ oc status
In project iuygaw-application on server https://api.na46.prod.nextcle.com:6443
svc/mysql - 172.30.114.192:3306
pod/mysql runs registry.redhat.io/rhel8/mysql-80:1
http://todoapi-iuygaw-application.apps.na46.prod.nextcle.com to pod port 30080 (svc/todoapi)
pod/todoapi runs quay.io/redhattraining/do180-todonodejs-12
View details with 'oc describe <resource>/<name>' or list resources with 'oc get all'.
[student@workstation ~]$ oc status | grep -o "http:.*com"
http://todoapi-iuygaw-application.apps.na46.prod.nextcle.com
# grep ^root: /etc/passwd /etc/shadow /etc/group | awk -F: 'BEGIN{OFS=":"}/shadow/{gsub(/.*/,"XXXXX",$3)}1'
/etc/passwd:root:x:0:0:root:/root:/bin/bash
/etc/shadow:root:XXXXX:18927:0:99999:7:::
/etc/group:root:x:0:
curl로 특정 파일 여러개 다운로드
- 아래와 같이 웹사이트의 특정 디렉토리 내에 여러가지 형태의 파일들이 포함되어있다.
# curl -s --list-only https://cdn.kernel.org/pub/linux/kernel/v5.x/
...
<a href="linux-5.9.9.tar.gz">linux-5.9.9.tar.gz</a> 18-Nov-2020 18:30 173M
<a href="patch-5.9.9.xz">patch-5.9.9.xz</a> 18-Nov-2020 18:30 491K
<a href="ChangeLog-5.9.9">ChangeLog-5.9.9</a> 18-Nov-2020 18:30 329K
-> 이 중에서 ChangeLog 파일만 별도로 다운 받고 싶다면 아래와 같이 진행
- 특정 파일들(ChangeLog 파일만 다운로드)
# for i in $(curl -s --list-only https://cdn.kernel.org/pub/linux/kernel/v5.x/ | grep ChangeLog | awk '{print $2}' | awk -F '"' '{print $2}')
do curl -O https://cdn.kernel.org/pub/linux/kernel/v5.x/$i
done
- 받은 ChangeLog 텍스트 파일의 내용에서 특정 패턴의 구문을 검색
# find . -type f | xargs grep 'xfs_btree_insert+0x1ec'
마지막 필드만 제외하고 출력 (awk)
- 마지막 필드만 제외하고 출력
# echo '/data/nice/abc/asda' | awk -F '/' 'sub(FS $NF,x)'
/data/nice/abc
- Path에서 최종 디렉토리만 출력
# basename /var/spool/cron
cron
정규표현식 사용 by 상우
상우 과장 잘 지내죠? ^^