본문 바로가기
대외활동/시스템프로그래밍

리눅스 쉘 프로그래밍

by hoshi03 2024. 8. 20.

• SED - 비대화형 편집기

sed 's/apple/banana_milk/g' test.txt

 

test.txt 에서 apple을 banana_milk로 치환

 

- 내용 추가해서 쓰기

 

• AWK

일반 스크립트 언어

awk -F':' '{ print $1, $3 } ' /etc/passwd

 

/etc/passwd 파일의 첫번째, 세번째 필드만 가져오기

 awk -F':' '/^root/, /^news/ { print $1, $3 } ' /etc/passwd

root 부터 news 까지의 1,3 필드만 가져오기

awk -F':' '$3 >= 1000 { print $1, $3 } ' /etc/passwd

세번째 필드의 값이 1000 이상인 값만 가져오기

$ ls -l | awk '/^-/ {print $9 $5}'

-로 시작하는 파일의 ls -l 명령어 수행결과의 9번, 5번 필드만 보여주기

$ ps -el | awk '$2=="R" {print $0}'

상태가 실행중인 프로세스의 정보만 보여주기

 

• 변수

city=seoul

ehco $city <- seoul 나온다

- 리스트 변수

 names = (kim lee park)

echo ${names[*]} <- 리스트 전체 출력

 echo ${#names[*]} <- 리스트 길이 출력

 echo ${names[1]} <- 리스트 1번 인덱스 원소 출력

 

 dirpath=/usr/bin/mypath

 

•조건문

 

test 변수 =="문자열"

echo $? 를 했을때 일치하면 0, 아니면 1 리턴

 

number=100
[ $number -eq 100 ] // number의 값이 100과 동일한지 비교
echo $?

 

#!/bin/bash
# if-then-fi
# ./if.sh user_name
if [ $# -ne 1 ]
then
    echo "Usage : $0 user_name"
    exit 1
fi
grep $1 /etc/passwd > /dev/null 2>&1

if [ $? -eq 0 ]
then
    echo "$1 is exist"
else
    echo "$1 is not exist"
fi

사용자 등록되었는지 판별하는 코드

 

read -p "enter username : " user

if who | grep $user >/dev/null 2>&1
then
    echo "$user is loggined"
else
    echo "$user is not loggined"
fi

입력 받아서 로그인된 사용자인지 판별하는 코드

 

- 이름 입력받아서 파일인지, 폴더인지, 존재하지 않는지 판별하는 코드 수정해서 작성해두기, 아래 코드는 돌아가지 않음

 

#!/bin/bash
# ./file_check.sh file_name
# 파일 유형, 파일의 권한을 점검하는 프로그램

echo "찾을 파일 정보 입력  : "
read file
if [ -e $file ]
then
    if [ -d $file ]
    then
        echo "$file is a directory"
    else
        if [ -f $file ]
        then
            ehco "$file is a file"
        fi
    fi
else
    echo "$file not exist!"
fi

 

• SecureCopy(scp)

원격 접속 프로토콜

 

• case 구문

 

상단의 . /etc~~ 구문에서 데이터를 가져와서 case 구문을 동작시킨다

. /etc/lsb-release
case $DISTRIB_ID in
"Ubuntu")
        echo "apt"
        ;;
"RHEL" )
        echo "yum"
        ;;
"Fedora"|"CentOS")
        echo "dnf"
        ;;
*)
        echo "can not recognized distribution"
        ;;
esac

 

 

# ./loop_stop.sh [start|stop]
case "$1" in
"start")
        if [ -f .loop ]
        then
                echo "loop was running"
        else
                ./loop >/dev/null 2>&1 &
                echo "loop is running"
                touch .loop
        fi
        ;;
"stop")

        if [ -f .loop ]
        then
                kill $(ps -u hoshi03 | grep loop | awk '{ print $1 }')
                echo "loop is dead"
                rm .loop


        else
                echo "already dead"
        fi
        ;;
*)
        echo "Usage: $0 [start|stop]"
        ;;
esac

 

무한 루프 코드 loop.c 상태를 보고 멈추는 switch 구문

 

for orgfile in *
do
        destfile=$(echo $orgfile | sed 's/[ -+]/_/g')
        if [ "$orgfile" != "$destfile" ]
        then
                echo "mv $orgfile $destfile"
                mv "$orgfile" $destfile
        fi
done

 

받은 파일명에 특수문자나 공백이 있으면 언더바로 전환하는 코드

 

• echo

echo '$var'의 경우에는 변수가 아닌 $var 형태로 나오게 된다

 

if/case/for문 복습

 

if [ -e $fname ]; then echo "1"; else echo "2"; fi
 case $num in "1"|"2") echo "apple"; ;; "3") echo "banana"; ;; *) echo "no fruits"; ;; esac

 

for문 변수를 묶어서 보내면 한번에 출력되고

묶지 않으면 하나씩 출력된다

 for var in "king queen prince princess"; do echo $var; done
for var in king queen prince princess; do echo $var; done
for var in $(who | awk '{ print $1 }') ; do echo $var; done

 

while문

#!/bin/bash
# while 조건식do ~done
count=0

while [ $count -lt 5 ]
do
        echo $count
        let count++
done
echo "escape while loop"

 

 

#!/bin/bash
# .login_check.sh
# 사용자 이름 입력ㅂㄱ받아 로그인한 상태인지 확인하는프로그램

read -p "enter username : " user

if who | grep $user >/dev/null 2>&1
then
    echo "$user is loggined"
    while true
    do
        echo "----------------------------------------------------------"
        ps -u $user | awk '$2 ~ /pts/ &&  $4 !=  "bash" { print $1, $4 }'
        echo "----------------------------------------------------------"
        sleep 3
    done
else
    echo "$user is not loggined"
fi

 

사용자를 입력받아 해당 사용자가 로그인한 상태면 정보를 로그파일에 저장하는 반복문

#!/bin/bash
# .login_check.sh
# 사용자 이름 입력ㅂㄱ받아 로그인한 상태인지 확인하는프로그램

read -p "enter username : " user


if who | grep $user >/dev/null 2>&1
then
    echo "$user is loggined"
    while true
    do
        who | grep $user >/dev/null 2>&1
        if (( $? != 0 ))
        then
                tty=$(tty)
                echo "$user is logout..." > $tty
                break
        fi
        echo "$(date +%H%M%S)-------------------------------------------"
        ps -u $user | awk '$2 ~ /pts/ &&  $4 !=  "bash" { print $1, $4 }'
        echo "----------------------------------------------------------"
        sleep 3
    done > ${user}_$(date +%Y%m%d).log
else
    echo "$user is not loggined"
fi

 

 

#!/bin/bash
# heredoc : <<

cat << CATEND
1. ls
2. ps
CATEND

while true
do
    echo -n "select : "
    read menuno

    case $menuno in
    "1")
        ls
        ;;
    "2")
        ps
        ;;
    "0")
        exit
        ;;
    "*")
        echo "invalid input"
        ;;
    esac
done

 

 

- 명령어 배열을 이용해서 명령어 수행

 

상단의 command=(ls ps exit)가 명령어 배열이고

${command[menuno-1]} 형태로 해당 인덱스의 명령을 수행한다

#!/bin/bash
# heredoc : <<

# 명령어 배열
command=(ls ps exit) 

cat << CATEND
1. ls
2. ps
0. exit
CATEND

while true
do
    echo -n "select : "
    read menuno
    if (( $menuno > 3 ))
    then
        echo "wrong choice"
    fi
    ${command[menuno-1]}
done

 

• 함수

 

func(){ ~} 형태로 정의하고 이름으로 호출한다

#!/bin/bash

myfunc()
{
    echo "myfunc: $1, $2"
    return 1
}


#funcion exec

echo "func exec first"
myfunc blue white
echo "func exec second"
myfunc red back

 

- 좀비 프로세스 판별해서 출력하는 코드

-복습

 

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(){
    if(fork()==0){
        sleep(3);
        system("ps -l");
        exit(0);
    }
    else{
        sleep(10);
        system("ps -l");
        sleep(100);
    }
}
#!/bin/bash

./process &
./process &
./process &


sleep 5

ppid=$(ps -el | awk '$2=="Z" { print $5 }')


if [ -n "$ppid" ]

then
    for pid in $ppid
    do
        #echo ${pid}
        ps -e | grep $pid | awk '{ print $1, $4 }'
    done
else
    echo "no process!"
fi