리눅스 shell

oogu ㅣ 2022. 5. 30. 22:47

@ 08_리눅스 쉘

 - 리눅스 사용자와 커널 사이에서 동작하는 인터페이스 역할을 담당하는 프로그램이다. 
 - 리눅스 사용자가 실행한 명령어를 해석하여 커널에게 전달하는 역할을 수행하기 때문에 명령어 해석기라고 한다.


1. 쉘 기능

 - 입력을 읽고 해당 명령행을 분석하여 커널에게 전달한다.

[root@Client1 /root]# ls -l /root
합계 8
-rw-------. 1 root root 1360 2022-03-24 16:25 anaconda-ks.cfg
-rw-r--r--. 1 root root 1732 2022-03-24 16:44 initial-setup-ks.cfg
drwxr-xr-x. 2 root root    6 2022-03-24 16:57 공개
drwxr-xr-x. 2 root root    6 2022-03-24 16:57 다운로드
drwxr-xr-x. 2 root root    6 2022-03-24 16:57 문서
drwxr-xr-x. 2 root root   40 2022-03-24 17:01 바탕화면
drwxr-xr-x. 2 root root    6 2022-03-24 16:57 비디오
drwxr-xr-x. 2 root root    6 2022-03-24 16:57 사진
drwxr-xr-x. 2 root root    6 2022-03-24 16:57 서식
drwxr-xr-x. 2 root root    6 2022-03-24 16:57 음악


 - 특수 문자를 분석하여 커널에게 전달한다.

[root@Client1 /root]# ls -l /etc/*.conf
-rw-r--r--. 1 root root       55 2021-12-23 14:04 /etc/asound.conf
-rw-r--r--. 1 root root    25696 2020-10-27 05:16 /etc/brltty.conf
-rw-r--r--. 1 root root     1085 2021-06-24 23:21 /etc/chrony.conf
-rw-r--r--. 1 root root     1174 2020-12-15 16:23 /etc/dleyna-server
~ 중간 생략 ~


 - 파이프, 리다이렉션, 백그라운드 프로세스를 처리한다.

[root@Client1 /root]# ls -l /etc/*.conf | grep resolv > nameserver.txt
[root@Client1 /root]# ls -l nameserver.txt 
-rw-r--r--. 1 root root 67 2022-03-26 11:26 nameserver.txt

[root@Client1 /root]# cat nameserver.txt 
-rw-r--r--. 1 root root       54 2022-03-26 11:16 /etc/resolv.conf

[root@Client1 /root]# rm -rf nameserver.txt 


2. 쉘 유형





3. 쉘 관련 사용자 환경 파일

1. profile

profile


2. profile.d

profile.d



3. .bash*

.bash*


4. bashrc

bashrc




 1) 계정 로그인 및 쉘이 실행될 때 다음과 같은 순서대로 해당 파일들이 읽혀진다.

 - 관리자가 일반 사용자의 환경을 설정 시켜 주는 경우

   /etc/profile  : 로그인 할 때만 읽혀짐
   /etc/bashrc   : 쉘이 실행 될때 마다 읽혀짐
   /etc/profile.d/*.sh : 쉘이 실행 될때 마다 읽혀짐

 - 일반 사용자가 자신의 환경을 설정 하는 경우

   $HOME/.bash_profile  : 로그인 할 때만 읽혀짐
   $HOME/.bashrc        : 쉘이 실행 될때 마다 읽혀짐


|─────────로그인──────────|──────쉘 실행 ──────|
/etc/profile           ->    $HOME/.bash_profile -> $HOME/.bashrc -> /etc/bashrc
/etc/profile.d/*.sh
①                                             ②                                 ③                       ④

 - ① : 시스템을 사용하는데 필요한 환경 변수 내용(모든 사용자에 적용되는 내용)들이 설정되어 있다. (cat /etc/profile)
 - ② : 계정이 필요한 환경 변수 내용(해당 계정에만 적용되는 내용)들이 설정되어 있다. 로그인 관련 배너 설정을 할 수 있다. (cat /root/.bash_profile)
 - ③ : 명령어를 자동으로 실행하기 위한 내용들이 설정되어 있다. (cat /root/.bashrc)
 - ④ : 모든 사용자에게 적용되는 전역 변수 내용들이 설정되어 있다. (cat /etc/bashrc)

①④ : 전역 변수
②③ : 지역 변수

 
 2) 계정 로그아웃할 때 다음과 같은 순서대로 해당 파일이 실행된다.

$HOME/.bash_logout -> $HOME/.bash_history 
① ②

 - ① : 로그아웃할때 실행되는 파일이며, 로그아웃 관련 배너 설정을 할 수 있다. (cat /root/.bash_logout)
 - ② : 로그인 중에 실행했던 명령어들을 로그아웃할때 저장하는 파일이다. (cat /root/.bash_history)

Ex1) 쉘 관련 사용자 환경 파일 실행 순서 확인

[root@Client1 /root]# vi /etc/profile
echo "|---> /etc/profile read" 

:wq


[root@Client1 /root]# vi /etc/profile.d/test.sh
#!/bin/bash

echo "|---> /etc/profile.d/*.sh read"

:wq


[root@Client1 /root]# vi .bash_profile 
echo "|---> ~/.bash_profile read"

:wq


[root@Client1 /root]# vi .bashrc
echo "|---> ~/.bashrc read"  

:wq


[root@Client1 /root]# vi /etc/bashrc
echo "|---> /etc/bashrc read" 

:wq


[root@Client1 /root]# vi .bash_logout 
echo "|---> ~/.bash_logout read" 

:wq


[root@Client1 /root]# ssh localhost
The authenticity of host 'localhost (::1)' can't be established.
ECDSA key fingerprint is SHA256:gQyEDJzQ+MfBS35oKwqpv4GAOX0iwXGvImQ9cpd6vd0.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'localhost' (ECDSA) to the list of known hosts.
root@localhost's password: 
Activate the web console with: systemctl enable --now cockpit.socket

Last login: Sat Mar 26 11:48:02 2022 from 192.168.2.1
|---> /etc/profile read
|---> /etc/profile.d/*.sh read
|---> /etc/bashrc read
|---> ~/.bash_profile read
|---> ~/.bashrc read
|---> /etc/bashrc read


[root@Client1 /root]# bash
|---> ~/.bashrc read
|---> /etc/bashrc read
|---> /etc/profile.d/*.sh read


[root@Client1 /root]# exit
exit

[root@Client1 /root]# exit
logout
|---> ~/.bash_logout read
Connection to localhost closed.


Ex2) user1으로 접속하여 실행된 파일 내용 및 순서 확인

[root@Client1 /root]# ssh user1@localhost
user1@localhost's password: 
Activate the web console with: systemctl enable --now cockpit.socket

Last login: Sat Mar 26 11:33:49 2022 from 192.168.2.1
|---> /etc/profile read
|---> /etc/profile.d/*.sh read
|---> /etc/bashrc read
|---> /etc/bashrc read


[user1@Client1 /home/user1]$ bash
|---> /etc/bashrc read
|---> /etc/profile.d/*.sh read

[user1@Client1 /home/user1]$ exit
logout

[user1@Client1 /home/user1]$ exit
logout
Connection to localhost closed.
[root@Client1 /root]# 


[참고] '.bash_history' 파일과 'history' 명령어 차이점

 - '.bash_history' 파일에는 로그인 중에 실행했던 명령어들을 로그아웃할때 저장하는 파일이다.
 - 'history' 명령어는 예전부터 로그인 중까지 실행했던 모든 명령어들을 확인할 수 있다.

[root@Client1 /root]# cat .bash_history 

[root@Client1 /root]# history 


 - 사용자가 로그인 하게 되면 사용자의 명령어를 저장하기 위해서 'history'를 위한 Stack 공간이 할당된다.
 - 이때, Bash 쉘은 기본 1000개 명령어까지 저장할 수 있으며, sh 쉘은 history 기능을 지원하지 않는다.


 - 다음 명령어를 실행하면 history 정보는 삭제되지만, 다시 로그인하면 '.bash_history' 파일에 의해서 복구된ㄴ다.

[root@Client1 /root]# history -c
[root@Client1 /root]# history 
    5  history 


 - 다음 내용을 알아보기 위해서 쉘 관련 사용자 환경 파일 설정 내용을 삭제한다.

[root@Client1 /root]# vi /etc/profile
  1 echo "|---> /etc/profile read" <- 삭제
  2 # /etc/profile

:wq


[root@Client1 /root]# rm -rf /etc/profile.d/test.sh  


[root@Client1 /root]# vi .bash_profile 
  1 echo "|---> ~/.bash_profile read" <- 삭제
  2 # .bash_profile

:wq


[root@Client1 /root]# vi .bashrc
  1 echo "|---> ~/.bashrc read"   <- 삭제
  2 # .bashrc

:wq


[root@Client1 /root]# vi /etc/bashrc
  1 echo "|---> /etc/bashrc read"  <- 삭제
  2 # /etc/bashrc

:wq


[root@Client1 /root]# vi .bash_logout 
  1 echo "|---> ~/.bash_logout read"  <- 삭제
  2 # ~/.bash_logout

:wq


[참고] $HOME/.bashrc 재실행

 - '$HOME/.bashrc' 파일 내용이 수정되고 적용되려면 쉘이 재실행되어야 한다.
 - 그렇기 때문에 로그아웃 한 이후에 다시 로그인하면 쉘이 실행되기 때문에 새로 변경된 '.bashrc' 내용이 실행된다.
 - 아니면 '. .bashrc', 'source .bashrc', 'source ~/.bashrc' 명령어를 이용하여 재실행해도 된다. 
 - 이때, 점(.)은 'source' 명령어와 같은 기능을 수행하지만, 권장하지는 않는다.
 - 즉, 스크립트 파일을 실행하려면 점(.), source, sh, bash 명령어를 사용하면 된다.


[참고] 'source'와 'bash' 스크립트 파일 실행 차이점

용도 사용 쉘 환경 변수 유효성 'cd'로 명령어에 대한 경로 유지

source    스크립트 파일 실행      현재 쉘        파일 밖에서 접근 가능 파일 밖에서 유지 가능
bash       스크립트 파일 실행      새로운 쉘     파일 밖에서 접근 불가능 파일 밖에서 유지 불가능


[참고] 스크립트 파일 실행하는 방법

[root@Client1 /root]# rm -rf test
[root@Client1 /root]# mkdir test
[root@Client1 /root]# cd test
[root@Client1 /root/test]# cat << EOF > ping.sh
#!/bin/bash // 스크립트 파일을 만들때 필요하다.

echo "Ping Test Shell Script"
ping -c 1 168.126.63.1
EOF

[root@Client1 /root/test]# file ping.sh
ping.sh: Bourne-Again shell script, ASCII text executable

[root@Client1 /root/test]# ls -l ping.sh 
-rw-r--r--. 1 root root 66 2022-05-30 10:41 ping.sh

Ex1) 'ping.sh' 스크립트 파일을 실행하기 위한 방법으로 틀린것은?

① sh ping.sh
② bash ping.sh
③ source ping.sh
④ . ping.sh
⑤ ./ping.sh


Ex2) 다음과 같은 방법으로 실행하려면 어떻게 해야하는가?

[root@Client1 /root/test]# ls -l ping.sh 
-rw-r--r--. 1 root root 66 2022-05-30 10:41 ping.sh

[root@Client1 /root/test]# ./ping.sh
-bash: ./ping.sh: 허가 거부



4. 쉘 변수

 - 변수는 파일로 동작하는 것이 아니라, 메모리에서 처리되며 동작한다.
 - 그렇기 때문에 재부팅되거나 로그아웃 이후 로그인하면 변수 내용을 사라진다.

 지역변수(Local Variable)              : # VAR=5 
 환경변수(Environment Variable)  : # export VAR=5 
 특수변수(Special Variable)           : $$, $?, $!, $0, $1, $#, $*.........


 1) 사용자 정의 변수

 - 사용자가 임의로 만들어서 사용하는 변수이며, 로그아웃 또는 재부팅되면 내용은 사라진다.
 - 만약, 로그인 중에 수동으로 삭제할 경우에는 unset 명령어를 사용한다.

[root@Client1 /root/test]# cd
[root@Client1 /root]# a=100
[root@Client1 /root]# b=200
[root@Client1 /root]# c=hello
[root@Client1 /root]# d="hello linux"
[root@Client1 /root]# 
[root@Client1 /root]# echo $a
100

[root@Client1 /root]# echo $a $b $c $d
100 200 hello hello linux

[root@Client1 /root]# unset a b c d
[root@Client1 /root]# echo $a $b $c $d


[root@Client1 /root]# cat /etc/sysconfig/network-scripts/ifcfg-ens33 
TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=none
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
NAME=ens33
UUID=5eefd56d-3a99-4156-b670-65a9e8532965
DEVICE=ens33
ONBOOT=yes
IPADDR=192.168.2.201
PREFIX=24
GATEWAY=192.168.2.254
DNS1=168.126.63.1


 - 'NIC'라는 이름으로 네트워크 장치 파일 변수 설정

[root@Client1 /root]# NIC=/etc/sysconfig/network-scripts/ifcfg-ens33 

[root@Client1 /root]# echo $NIC
/etc/sysconfig/network-scripts/ifcfg-ens33

[root@Client1 /root]# cat $NIC
TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=none
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
NAME=ens33
UUID=5eefd56d-3a99-4156-b670-65a9e8532965
DEVICE=ens33
ONBOOT=yes
IPADDR=192.168.2.201
PREFIX=24
GATEWAY=192.168.2.254
DNS1=168.126.63.1


 - NIC 변수는 'set' 명령어로 확인은 가능하지만, 환경 변수로 등록을 하지 않았기 때문에 'env' 명령어로를 검색되지 않는다.

[root@Client1 /root]# set | grep NIC
NIC=/etc/sysconfig/network-scripts/ifcfg-ens33

[root@Client1 /root]# env | grep NIC


 - 'bash'를 하나 더 실행하여 'NIC' 변수 내용을 확인한다.

[root@Client1 /root]# bash
[root@Client1 /root]# ps -f
UID          PID    PPID  C STIME TTY          TIME CMD
root        4012    4011  0 10:09 pts/0    00:00:00 -bash
root        6020    4012  0 11:34 pts/0    00:00:00 bash
root        6048    6020  0 11:34 pts/0    00:00:00 ps -f


[root@Client1 /root]# echo $NIC

[root@Client1 /root]# set | grep NIC
[root@Client1 /root]# env | grep NIC

[root@Client1 /root]# exit
exit


 - 재접속 이후 'NIC' 변수 내용 확인

[root@Client1 /root]# exit
logout

[root@Client1 /root]# echo $NIC

[root@Client1 /root]# set | grep NIC
[root@Client1 /root]# env | grep NIC


 2) 환경 변수

 - 자주 사용하는 사용자 정의 변수를 환경 변수에 저장하면, 다음 로그인 및 재부팅할때도 사용이 가능하다.
 - 그렇기 때문에 환경 변수를 '.bash_profile'에 설정하면 다음 로그인 및 재부팅할때 사용할 수 있다.
 - 변수 이름은 대문자를 사용하는 것을 권장하며, 'env' 명령어를 이용하여 확인할 수 있다.

[root@Client1 /root]# env
~ 중간 생략 ~

SSH_CONNECTION=192.168.2.1 63247 192.168.2.201 22
LANG=ko_KR.UTF-8
HISTCONTROL=ignoredups
HOSTNAME=Client1
which_declare=declare -f
XDG_SESSION_ID=18
USER=root
SELINUX_ROLE_REQUESTED=
PWD=/root
SSH_ASKPASS=/usr/libexec/openssh/gnome-ssh-askpass
HOME=/root
SSH_CLIENT=192.168.2.1 63247 22
SELINUX_LEVEL_REQUESTED=
XDG_DATA_DIRS=/root/.local/share/flatpak/exports/share:/var/lib/flatpak/exports/share:/usr/local/share:/usr/share
SSH_TTY=/dev/pts/0
MAIL=/var/spool/mail/root
TERM=linux
SHELL=/bin/bash
SELINUX_USE_CURRENT_RANGE=
SHLVL=1
LOGNAME=root
DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/0/bus
XDG_RUNTIME_DIR=/run/user/0
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
PS1=[\u@\h $PWD]# 
HISTSIZE=1000
LESSOPEN=||/usr/bin/lesspipe.sh %s
BASH_FUNC_which%%=() {  ( alias;
 eval ${which_declare} ) | /usr/bin/which --tty-only --read-alias --read-functions --show-tilde --show-dot $@
}
_=/usr/bin/env


[root@Client1 /root]# env | grep HOSTNAME
HOSTNAME=Client1

[root@Client1 /root]# env | grep USER
USER=root

[root@Client1 /root]# env | grep PATH
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin

[root@Client1 /root]# env | grep HOME
HOME=/root

[root@Client1 /root]# echo $HOSTNAME
Client1

[root@Client1 /root]# echo $USER
root

[root@Client1 /root]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin

[root@Client1 /root]# echo $HOME
/root
 

 3) 변수 관련 명령어

 - env : 전역 변수 설정 및 확인하는 명령어(# env 변수명=변수값)
 - set : 사용자 환경 변수 설정 및 확인하는 명령어(# set 변수명=변수값)
 - export : 쉘 변수를 환경 변수로 변경(등록)해주는 명령어(# export 변수명)

Ex) PS1, PS2 환경 변수 확인

 - 현재 실습 환경에서 PS1 환경 변수는 전역 변수로 설정(등록)되어 있기 때문에 'env' 명령어로 확인이 가능하다. 

[root@Client1 /root]# cat .bashrc | tail -4
alias vi='vim'
alias ls='ls --color=auto --time-style=long-iso'
PS1="[\u@\h \$PWD]# "
export PS1


[root@Client1 /root]# env | grep PS1
PS1=[\u@\h $PWD]# 

[root@Client1 /root]# echo $PS1
[\u@\h $PWD]#


 - PS2 환경 변수는 사용자 환경 변수로 설정되어 있기 때문에 'set' 명령어만로 확인할 수 있다.

[root@Client1 /root]# env | grep PS2

[root@Client1 /root]# set | grep PS2   
PS2='> '

[root@Client1 /root]# echo $PS2
>


[참고] PS2 환경 변수

 - 명령어가 아직 끝나지 않았음을 나타낼 때 사용하는 프롬프트를 정의하는 변수이다.

[root@Client1 /root]# ls -a \
> -l
합계 4
drwxr-xr-x.  2 root root    6 2022-03-26 11:30 .
dr-xr-x---. 17 root root 4096 2022-03-26 11:43 ..


 4) 사용자 정의 변수를 환경 변수에 저장하는 방법

 - 'export' 명령어를 사용하면 환경 변수를 저장한다.

[root@Client1 /root]# NIC=/etc/sysconfig/network-scripts/ifcfg-ens33 

[root@Client1 /root]# set | grep NIC
NIC=/etc/sysconfig/network-scripts/ifcfg-ens33

[root@Client1 /root]# env | grep NIC


[root@Client1 /root]# export NIC

[root@Client1 /root]# env | grep NIC
NIC=/etc/sysconfig/network-scripts/ifcfg-ens33

[root@Client1 /root]# echo $NIC
/etc/sysconfig/network-scripts/ifcfg-ens33


 - 'bash'를 하나 더 실행하여 'NIC' 변수 내용을 확인한다.

[root@Client1 /root]# bash
[root@Client1 /root]# ps -f
UID          PID    PPID  C STIME TTY          TIME CMD
root        6074    6073  0 11:35 pts/0    00:00:00 -bash
root        6236    6074  0 11:42 pts/0    00:00:00 bash
root        6266    6236  0 11:42 pts/0    00:00:00 ps -f

[root@Client1 /root]# env | grep NIC
NIC=/etc/sysconfig/network-scripts/ifcfg-ens33

[root@Client1 /root]# echo $NIC
/etc/sysconfig/network-scripts/ifcfg-ens33

[root@Client1 /root]# cat $NIC | tail -4
IPADDR=192.168.2.201
PREFIX=24
GATEWAY=192.168.2.254
DNS1=168.126.63.1

[root@Client1 /root]# exit
exit


 - 재접속 이후 'NIC' 변수 내용 확인

[root@Client1 /root]# exit
logout

[root@Client1 /root]# set | grep NIC
[root@Client1 /root]# env | grep NIC
[root@Client1 /root]# 
[root@Client1 /root]# echo $NIC


 - 환경 변수에 NIC 변수를 계속 적용하는 방법

[root@Client1 /root]# vi .bash_profile  // '.bashrc' 파일에 설정해도 무관함

 14 NIC=/etc/sysconfig/network-scripts/ifcfg-ens33
 15 export NIC

:wq


 - 재접속 이후 'NIC' 변수 내용 확인

[root@Client1 /root]# exit
logout

[root@Client1 /root]# env | grep NIC
NIC=/etc/sysconfig/network-scripts/ifcfg-ens33

[root@Client1 /root]# echo $NIC
/etc/sysconfig/network-scripts/ifcfg-ens33

[root@Client1 /root]# cat $NIC | tail -4
IPADDR=192.168.2.201
PREFIX=24
GATEWAY=192.168.2.254
DNS1=168.126.63.1


[참고] $HOME/.bash_profile 재실행

 - $HOME/.bash_profile 파일 내용이 수정되고 적용되려면 쉘이 재실행되어야 한다.
 - 그렇기 때문에 로그아웃 한 이후에 다시 로그인하면 쉘이 실행되기 때문에 새로 변경된 '.bash_profile' 내용이 실행된다.
 - 아니면 '. .bash_profile', 'source .bash_profile', 'source ~/.bash_profile' 명령어를 이용하여 재실행해도 된다. 
 - 이때, 점(.)은 'source' 명령어와 같은 기능을 수행하지만, 권장하지는 않는다.
 - 즉, 스크립트 파일을 실행하려면 점(.), source, sh, bash 명령어를 사용하면 된다.



Ex1) .bash_profile 예제

 - AA 변수에 100, BB 변수에 200을 선언하고, 로그인될때 마다 적용되도록 구성한다.
 - 구성이 완료되었다면, 로그아웃/로그인 진행 없이 바로 적용되도록 한다.

[root@Client1 /root]# env | egrep "AA|BB" 
AA=100
BB=200

[root@Client1 /root]# echo $AA $BB
100 200


Ex2) .bashrc 예제

 - .bashrc 파일에 alias pg='ps -ef | grep $1' 를 추가한다. 
 - 추가가 완료되었다면, 로그아웃/로그인 진행 없이 'pg sleep' 명령어가 가능하도록한다.

[root@Client1 /root]# pg sleep
root        6519     952  0 11:51 ?        00:00:00 sleep 60
root        6555    6381  0 11:52 pts/0    00:00:00 grep --color=auto sleep





'리눅스' 카테고리의 다른 글

프로세스 관리  (0) 2022.05.30
권한  (0) 2022.04.07
vi, vim 편집기  (0) 2022.04.03
압축 및 아카이빙  (0) 2022.04.03
리눅스 계정  (0) 2022.04.03