본문 바로가기
네이버클라우드/Linux

Linux 8일차 (2023-05-03) Shell Script

by prometedor 2023. 5. 3.

shell의 종류

종류설명
Bourne Shell (sh)79년. Bell 연구소 Steven Bourne 이 개발
C Shell (csh)버클리 대학교에서 Bill joy 가 개발
C 언어와 비슷한 문법을 사용
TC Shell (tcsh)C Shell 의 확장판
Korn Shell (bash)AT&T 사의 David Korn 이 개발
Bourne Shell 의 확장판
Bourne Again Shell (bash)Bourne Shell 을 기반으로 C Shell 과 Korn Shell 의 장점까지 포함한 강력한 shell
자유 소프트웨어 재단의 Brian fox 가 개발
Linux 의 기본 쉘
Debian Shell (dash)데비안 리눅스 배포판에서 사용하는 Shell
많이 사용하지는 않음
ZshPaul Falstad 가 개발

 

root@ysy:~# echo $SHELL  --> 내가 있는 쉘의 위치
/bin/bash

root@ysy:~/d8# nl /etc/shells  --> 사용 가능한 쉘(shell) 목록
     1  # /etc/shells: valid login shells
     2  /bin/sh
     3  /bin/bash
     4  /usr/bin/bash
     5  /bin/rbash
     6  /usr/bin/rbash
     7  /usr/bin/sh
     8  /bin/dash
     9  /usr/bin/dash
    10  /usr/bin/tmux
    11  /usr/bin/screen
    
root@ysy:~/d8# ai ksh --> ksh 설치
# history
1       cd  --> 작동 안 됨
2       h	--> 작동 안 됨
3       clear  --> bash 에서 ctrl + L
4       history  --> 목록 보기
# exit

ㄴ history, alias, job, control 기능 사용 불가
 

쉘 스크립트 파일을 이용한 실습

쉘 스크립트 파일로 날짜 커스텀하여 저장 후 실행

root@ysy:~/d8# vi a1.sh

ㄴ a1 이라는 쉘 스크립트 파일 생성
ㄴ -e 옵션 : 줄바꿈
ㄴ 주석은 # 으로 함
 

root@ysy:~/d8# a1.sh
a1.sh: command not found  --> 경로 설정 해주어야 함 : ./ 추가

root@ysy:~/d8# ./a1.sh
-bash: ./a1.sh: Permission denied  --> 권한 설정 필요

root@ysy:~/d8# chmod +x a1.sh  --> 실행 권한 추가
--> 보통은 chmod 755 로 설정함

root@ysy:~/d8# PATH=$PATH:.  --> 경로에 현재 위치 추가

 

날짜 출력 커스텀하여 alias 추가하기

root@ysy:~/d8# alias date='date +%Y년%m월%d일::%H시%M분'
root@ysy:~/d8# date
2023년05월03일::20시12분


root@ysy:~/d8# alias
alias date='date +%Y년%m월%d일::%H시%M분'
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
alias grep='grep --color=auto'
alias l='ls -CF'
alias la='ls -A'
alias ll='ls -alF'
alias ls='ls --color=auto'

 

** 추가 : 입력 중 내용 편집 방법

<ctrl> + U	--> 통째로 지우기
<ctrl> + W	--> 단어 단위로 지우기
<ctrl> + a	--> 커서 맨 앞으로 이동
<ctrl> + e	--> 커서 맨 뒤로 이동
p			--> 위 방향키 기능
n			--> 아래 방향키 기능
history		--> !번호 : history 번호에 있는 명령 실행
!!			--> 바로 이전 명령 실행
<ESC> + .	--> 아래 방향키 기능
<Alt> + .	--> 위 방향키 기능

 
 

리눅스 종료 상태 코드

코드의미
0성공
1알 수 없는 오류, 일반적인 error
2명령어 잘못 사용, Syntax error
127명령어를 찾을 수 없음
Shell 의 종료 상태   참 : 0, 거짓 : 0 이 아닌 모든 값

echo $?  --> 바로 이전 상태 종료 값 출력

ㄴ 함수 종료 : return
ㄴ 스크립트 종료 : exit
 
 

redirection

문자의미
<입력
>출력
>>덧붙임 (덮어씌움)
2>파일파일로 에러를 redirect
실행결과 &>실행결과와 에러를 덧붙여 출력
&> file표준 출력과 표준에러를 동시에 file 로 redirect
>& file표준 출력과 표준에러를 동시에 file 로 redirect
  
cal 1> b표준 출력을 파일로 출력
cal 0< b파일로부터 입력받아 cat 실행
  
date >> bb 파일에 date 결과 덧붙임 (덮어씌움)
  
root@ysy:~/d8# date > a5  --> 1이 생략되어 있는 것
root@ysy:~/d8# date 1> a6
root@ysy:~/d8# nl a5
     1  2023년05월03일::20시36분
root@ysy:~/d8# nl a6
     1  2023년05월03일::20시36분
     
     
     
root@ysy:~/d8# cal 1> b  --> 표준 출력을 파일로 저장
root@ysy:~/d8# cat 0< b  --> 파일로부터 입력 받아 cal 실행
      May 2023
Su Mo Tu We Th Fr Sa
    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

root@ysy:~/d8# cal > b  --> 1이 생략된 것
root@ysy:~/d8# cat < b  --> 0이 생략된 것
      May 2023
Su Mo Tu We Th Fr Sa
    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



root@ysy:~/d8# aslkjf sajflk sljfsj 2> a12  --> 표준 에러를 파일로 저장
root@ysy:~/d8# nl a12
     1  aslkjf: command not found

root@ysy:~/d8# saldl sjflj jsdlif 2>/dev/null  --> 표준 에러를 /dev/null 로 날려버리기

 

명령을 쉘 스크립트에 저장해서 파일로 실행

root@ysy:~# vi init_1.sh

 

 

root@ysy:~# chmod +x init_1.sh  --> 실행 권한을 부여해야 함

root@ysy:~# ./init_1.sh  --> PATH=PATH:. 설정을 하지 않을 경우 이처럼 ./ 을 추가해서 실행해야 함

 
 

초기화 작업 시작과 끝을 시간으로 나타내보기

root@ysy:~# now=`date +%Y년%m월%d일::%H시%M분`
root@ysy:~# echo $now
2023년05월03일::21시08분
root@ysy:~# echo " 초기화 작업 시작 : $now " >> init_ex.txt

root@ysy:~# now=`date +%Y년%m월%d일::%H시%M분`
root@ysy:~# echo " 초기화 작업 끝 : $now " >> init_ex.txt
root@ysy:~# nl init_ex.txt
     1   초기화 작업 시작 : 2023년05월03일::21시08분
     2   초기화 작업 끝 : 2023년05월03일::21시20분

 
 

변수에 값 저장 및 출력 해보기

root@ysy:~# read a
300
root@ysy:~# echo $a
300
root@ysy:~# read a b
9 3
root@ysy:~# echo $a $b
9 3
root@ysy:~# echo $a $b $c
9 3
root@ysy:~# read a b c
asdf 40 4.5
root@ysy:~# echo $a $b $c
asdf 40 4.5


root@ysy:~# read a b c  --> 변수 3개
slk 33 5.5 66666 slkf jj  --> 값 5개
root@ysy:~# echo $a $b $c
slk 33 5.5 66666 slkf jj
root@ysy:~# echo $a
slk
root@ysy:~# echo $b
33
root@ysy:~# echo $c  --> c에 나머지가 전부 다 들어감
5.5 66666 slkf jj

 
 

쉘 스크립트 예제

root@ysy:~# mkdir d80 && cd d80
root@ysy:~/d80# vi b.sh

#!/bin/bash
echo " 스크립트 이름 : $0 "  --> 파일 이름
echo " \$1 : $1 "  
echo " \$2 : $2 "
echo " \$3 : $3 "
echo " \$4 : $4 "
echo " argument 개수 : $# "
echo " 모든 값 출력  : $* "


root@ysy:~/d80# ./b.sh 20 60 50 70 80
 스크립트 이름 : ./b.sh  --> $0
 $1 : 20				 --> $1
 $2 : 60				 --> $2
 $3 : 50				 --> $3
 $4 : 70				 --> $4
 argument 개수 : 5
 모든 값 출력  : 20 60 50 70 80

 

#!/bin/bash
echo " 스크립트 이름 : $0 "
echo " $1 : $1 "  #--> $1 이라는 문자 자체를 뿌리고 싶을 경우 \ (escape문자) 를 넣어줌
echo " \$2 : $2 "
echo " \$3 : $3 "
echo " \$4 : $4 "
echo " argument 개수 : $# "
echo " 모든 값 출력  : $* "

root@ysy:~/d80# ./b.sh 20 60 50 70 80
 스크립트 이름 : ./b.sh
 20 : 20
 $2 : 60
 $3 : 50
 $4 : 70
 argument 개수 : 5
 모든 값 출력  : 20 60 50 70 80
 모든 값 출력  : 20 60 50 70 80

 

 

BASH shell 특수 값

문자의미
$?바로 이전 명령의 상태 종료 값
$$현재 SHELL PID (프로세스 아이디)
$0실행중인 프로그램 이름
$#인수의 개수
$*$1, $2, $3 ... 모든 매개변수를 하나로 참조
$@$1, $2, $3 ... 모든 매개변수를 개별 참조

 
 

BASH shell 메타문자

문자의미
*0개 이상의 문자와 일치
?단일 문자와 일치
[...]대괄호 안에 있는 문자 중 하나와 일치
||이전 명령어의 실행 결과가 실패일 경우 실행되는 논리합(OR) 연산자
&&이전 명령어의 실행 결과가 성공일 경우 실행되는 논리곱(AND) 연산자
;명령어 여러개 가능 -> enter 역할
$$현재 프로세스 아이디 (PID)
$?바로 이전 명령의 상태 종료 값

 

root@ysy:~/d80# vi a1.c

#include <stdio.h>
int main(int a, char* b[])
{
        int i=0;
        printf(" 인수의 개수 = %d \n", a);
        for (i=0; i<a; i++)
                printf(" \b[%d] ==> %s \n", i, b[i]);
        return 0;
}

root@ysy:~/d80# gcc -o a1 a1.c

root@ysy:~/d80# ./a1 aa bb 30 50
 인수의 개수 = 5
[0] ==> ./a1
[1] ==> aa
[2] ==> bb
[3] ==> 30
[4] ==> 50

root@ysy:~/d80# echo $?  --> 이전 명령어의 상태 종료 값
0  --> 상태 종료 값이 0으로 출력됨 (c 파일에서 return 0 했으므로 )




root@ysy:~/d80# vi a1.c

#include <stdio.h>
int main(int a, char* b[])
{
        int i=0;
        printf(" 인수의 개수 = %d \n", a);
        for (i=0; i<a; i++)
                printf(" \b[%d] ==> %s \n", i, b[i]);
        return 50;  --> 이 값을 50으로 설정할 경우
}

root@ysy:~/d80# gcc -o a1 a1.c

root@ysy:~/d80# ./a1 aa bb 30 50
 인수의 개수 = 5
[0] ==> ./a1
[1] ==> aa
[2] ==> bb
[3] ==> 30
[4] ==> 50
root@ysy:~/d80# echo $?
50  --> 상태 종료 값이 50으로 출력됨 (c 파일에서 return 50 했으므로 )

ㄴ 스크립트에서는 0번째가 스크립트의 이름임 => 인수의 개수는 파일이름을 뺀 나머지를 카운트 한 것
 

;

root@ysy:/etc/ssh# cal; date; who;  --> ; 는 enter 기능을 함
      May 2023
Su Mo Tu We Th Fr Sa
    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

Wed May  3 04:28:44 PM UTC 2023
j        tty1         2023-05-03 14:52
j        pts/0        2023-05-03 14:53
j        pts/1        2023-05-03 14:53 (10.0.2.2)
j        pts/2        2023-05-03 14:53 (10.0.2.2)




root@ysy:/etc/ssh# cal && date && who  --> cal, date, who 모두 출력
      May 2023
Su Mo Tu We Th Fr Sa
    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

Wed May  3 04:31:38 PM UTC 2023
j        tty1         2023-05-03 14:52
j        pts/0        2023-05-03 14:53
j        pts/1        2023-05-03 14:53 (10.0.2.2)
j        pts/2        2023-05-03 14:53 (10.0.2.2)




root@ysy:/etc/ssh# cal || date || who  --> 맨 앞에 cal 이 참이므로 뒤에는 출력하지 않음
      May 2023
Su Mo Tu We Th Fr Sa
    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

 
 

bash 입력과 출력

root@ysy:~/d80# read
100
root@ysy:~/d80# echo $REPLY  --> 디폴트로 여기에 저장됨
100

root@ysy:~/d80# echo "사는 곳은 : " ; read town
사는 곳은 :
역삼동
root@ysy:~/d80# echo $town
역삼동

root@ysy:~/d80# echo -n "사는 곳은 : " ; read town; echo $town
사는 곳은 : 방배동
방배동



root@ysy:~/d80# echo -n "사는 곳은 : " ; read town; echo "우리집은 $town"
사는 곳은 : 인천시
우리집은 인천시

root@ysy:~/d80# read -p "사는 곳은 : " town; echo "우리집은 $town"
사는 곳은 : 울산시
우리집은 울산시