반응형

pip

python3-pip 혹은 버전에 맞는 pip를 설치해서 써야하는 python 패키지 관리자로 python package를 관리하기엔 필수적으로 사용하는데, python을 거의 처음 사용하다보면 이게 쉽지가 않다.

venv, uv, PYTHONPATH

Python 이라는게 불리는 PYTHONPATH 를 기준으로 (없으면 default 경로로) bin/ lib 등등을 찾아가기 때문에, PYTHONPATH만 별도로 지정이 되면 Python 환경에서 속히 말하는 가상화가 된다.
그걸 이용해서 venv 패키지는 원하는 경로에 venv 폴더를 만들어 각 Task마다 별도의 venv환경을 만들어 꾸밀 수가 있다.
uv는 Rust로 pip를 재구현하여 pip와 실제 구현은 다르다. 하지만 동작은 pip의 동작과 동일하다. uv를 통해서 venv 환경에 접근도 가능하다.

주의... 알면서도...

문제는 pip는 Python을 쓰려면 필수인데, venv로 쓰는 패키지가 있고 uv를 사용하는 패키지도 있고, Host에 깔린 패키지도 있다.
자신이 pip로 패키지를 확인할때는 반드시 주의 해야 한다.
알면서도... 알면서도... 자꾸 뻘짓을 하게 된다.

아래의 세개는 다르다.

pip

$ pip list 

이건 Host에 python3-pip를 설치하고 해당 pip가 우선적으로 되어 있을 경우 설치된 python3-pip 패키지의 pip를 사용하는 것이다.
venv를 사용하는 환경이면 venv activate된 path를 바라보게 되어 python3, lib 모두 해당 경로를 참조하는 경우에도,
Host의 pip 명령어를 치면 activate된 venv경로가 아닌 default로 /usr/bin/pip를 호출하게 되고 이 pip는 바라보는 lib의 path를 venv환경이 아닌 host의 환경을 바라보게 된다.

python3 -m pip

$ python3 -m pip list

이 명령어는 venv가 활성화된 ${PYTHONPATH}/lib의 Python package list를 보여준다.
기본적으로 python3-pip 패키지의 pip 바이너리를 직접적으로 호출하는게 아닌 Python3 pip 모듈을 호출하는 것이기 때문에 python3 바이너리를 호출하고, 이 python3 바이너리는 venv 환경이든 uv환경이든(uv환경도 venv환경과 동일한 영향을 받으므로 venv환경과 동일하겠지만) PATH가 잡힌곳의 python3를 호출하므로 더 안전하다.

uv pip list

$ uv pip list

uv환경을 쓸 경우 이 방법도 PYTHONPATH의 lib에 있는 package를 바라보게 되기 때문에 venv환경의 영향을 받는다.

패키지 확인 전에...

  1. venv환경을 써야 되는 경우가 있다면, 그냥 python3-pip 패키지를 지울 수 있다면 지워버리자.
  2. 무조건 $ python3 -m pip로 명령어를 습관화 하자.
  3. 그렇더라도 중요한 실행 전에는 그냥 아래 세개 명령어 다 때려넣어서 세개중 하나라도 다르다면 지금 pip 호출되는 애들이 다르다는 것이니 주의 해야 한다는 생각을 하자
    $ pip list 
    $ python3 -m pip list
    $ uv pip list

파이썬...

하..역시 스크립트는 나랑 안맞아...

반응형
반응형

Shell CMD

$ git submodule foreach --recursive '
  realpath $toplevel/$path | xargs -I{} git config --global --add safe.directory "{}"
'
반응형
반응형

tmux에서 마우스 스크롤 안 되는 문제 해결

tmux 기본 설정에서는 마우스 휠로 스크롤해도 터미널 출력 내용이 올라가지 않음.
이유는 tmux가 자체적으로 출력 버퍼를 가지고 있어서, 일반 터미널처럼 동작하지 않기 때문임.

활성화 방법

.tmux.conf에 아래 설정 추가:

# 마우스 기능 켜기
set -g mouse on

# (선택사항) copy-mode 내에서 마우스 휠로 스크롤 활성화
bind -T copy-mode-vi WheelUpPane send-keys -X scroll-up  
bind -T copy-mode-vi WheelDownPane send-keys -X scroll-down

적용 방법

  1. tmux 세션 완전 종료 후 재시작
  2. 실행중인 세션에서 설정 파일 Re-load
    $ tmux source-file ~/.tmux.conf
반응형
반응형

tmux

tmux (Terminal Multiplexer) 는 단일 화면에서 여러 terminal 을 생성, 관리하는 도구이며, ssh/telnet과 별도 독립 세션으로 유지되어, ssh/telnet session의 종료와 무관하게 언제든 dettach, attach 해서 session을 재사용/중지 할 수 있다.

Usage

세션 생성

$ tmux new -s <session_name>

세션 목록 조회

$ tmux ls

세션 재연결

$ tmux attach -t <session_name>

세션 강제 종료

$ tmux kill-session -t <session_name>

tmux session 내에서 명령

세션 detach

ctrl + b d

세션 종료

ctrl + b &

exit 는 현재 pane 를 종료하므로 다른 기능임

pane 분할

  • ctrl + b % : 세로로 pane 분할
  • ctrl + b " : 가로로 pane 분할
  • ctrl + b q : pane index를 화면에 출력
  • ctrl + b ! : 분할된 pane 전체 제거
  • ctrl + b x : 현재 pane 제거 (삭제 전 y/n 입력)
  • ctrl + d : 현재 pane 제거 (즉시).

exit 명령어 입력과 동일한 동작

  • ctrl + b ' : prompt 에 pane index 를 입력해 이동
  • ctrl + b <방향키> : 분할된 pane 사이에서 이동
  • ctrl + b : : promt 로 명령어 입력
    • resize-pane -L or -R or -U or -D : pane 사이즈 조절
      ex) resize-pane -U 5 : 5 cell 만큼 upwindow
  • ctrl + b w : window 목록 보기
  • ctrl + b c : 새로운 window 생성
  • ctrl + b p : 이전 window 로 이동
  • ctrl + b n : 다음 window 로 이동
  • ctrl + b l : 마지막 window 로 이동
  • ctrl + b <번호> : 번호에 해당하는 window 로 이동
  • ctrl + b f : prompt 에 이름 입력하여 해당 window 로 이동기타
  • ctrl + b ? : 단축키 목록 표시
  • ctrl + b : : tmux 명령어 입력
  • ctrl + b [ : 스크롤 활성화
반응형
반응형

Kernel 버전

커널버전은 항상 설치된 버전 중에서 최 상위 버전으로 항상 default로 선택 가능하게 되어 있다.
드라이버는 커널 버전에 정확한 숫자에 의존성을 가지고 있기 때문에 사용하는 드라이버가 특정 버전 커널에만 의존적이거나 지원이 된다면, 커널 버전이 올라갈 경우 해당 디바이스는 사용이 불가하기 때문에 가끔 특정 커널 버전에 고정을 해야 하는 경우가 있따.

Kernel 과거 버전 고정하기

현재 설치된 커널 버전 확인

$ sudo dpkg --list | egrep -i --color 'linux-image|linux-headers'

이 명령어로 앞에 ii 또는 ic 라고 나올 수 있는데 각 의미는 아래와 같다.

  • ii : ‘It should be installed and it is installed’
  • rc : ‘It’s removed/uninstalled but it’s configuration files are still there’
    당연하지만 이미 설치된 커널 버전 으로 고정이 가능하다.
    설치가 되지 않았을 경우에는 원하는 커널을 설치 후에 진행해야 한다.

명령어를 시행하면 아래의 형식으로 내용이 출력된다.

ii  linux-headers-6.5.0-18-generic             6.5.0-18.18~22.04.1                     amd64        Linux kernel headers for version 6.5.0 on 64 bit x86 SMP
ii  linux-headers-6.8.0-48-generic             6.8.0-48.48~22.04.1                     amd64        Linux kernel headers for version 6.8.0 on 64 bit x86 SMP
ii  linux-headers-generic-hwe-22.04            6.8.0-48.48~22.04.1                     amd64        Generic Linux kernel headers
ii  linux-image-6.5.0-18-generic               6.5.0-18.18~22.04.1                     amd64        Signed kernel image generic
ii  linux-image-6.8.0-48-generic               6.8.0-48.48~22.04.1                     amd64        Signed kernel image generic
ii  linux-image-generic-hwe-22.04              6.8.0-48.48~22.04.1                     amd64        Generic Linux kernel image

$menuentry_id_option

menuentry_id_option은 GRUB에서 설정에서 사용되는 옵션으로 각 부팅의 항목의 UUID로 사용된다. 이것은 GRUB Bootloader에서 여러개의 커널 항목에서 특정 항목에 사용되는 ID를 정의한다. 여기에 특정 커널의 UUID로 지정을 해줄 경우 Bootloader에서 해당 커널로 Boot sequence를 진행하게 된다.

$ grep submenu /boot/grub/grub.cfg 

명령어를 실행하면 아래와 같은 형식으로 출력된다.

submenu 'Advanced options for Ubuntu' $menuentry_id_option 'gnulinux-advanced-b7e9ad35-1a1f-45e3-9cfd-084a7ce27282' {

위의 출력 내용 중 gnulinux-advanced-b7e9ad35-1a1f-45e3-9cfd-084a7ce27282 내용을 아래에서 사용하니 저장해둔다.

Kernel 정보 확인

$ grep gnulinux /boot/grub/grub.cfg

커널에서 원하는 커널 정보를 확인한다.

menuentry 'Ubuntu' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-simple-b7e9ad35-1a1f-45e3-9cfd-084a7ce27282' {
submenu 'Advanced options for Ubuntu' $menuentry_id_option 'gnulinux-advanced-b7e9ad35-1a1f-45e3-9cfd-084a7ce27282' {
  menuentry 'Ubuntu, with Linux 5.4.0-42-generic' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-5.4.0-42-generic-advanced-b7e9ad35-1a1f-45e3-9cfd-084a7ce27282' {
  menuentry 'Ubuntu, with Linux 5.4.0-42-generic (recovery mode)' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-5.4.0-42-generic-recovery-b7e9ad35-1a1f-45e3-9cfd-084a7ce27282' {
  menuentry 'Ubuntu, with Linux 5.4.0-39-generic' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-5.4.0-39-generic-advanced-b7e9ad35-1a1f-45e3-9cfd-084a7ce27282' {
  menuentry 'Ubuntu, with Linux 5.4.0-39-generic (recovery mode)' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-5.4.0-39-generic-recovery-b7e9ad35-1a1f-45e3-9cfd-084a7ce27282' {

만약에 위의 커널 정보 중에서 5.4.0-42-generic 을 사용하고 싶을 경우 gnulinux-5.4.0-42-generic-advanced-b7e9ad35-1a1f-45e3-9cfd-084a7ce27282을 사용하면 된다.

grub 설정

grub에 default에 대한 항목을 아래와 같이 설정해준다.

$ sudo vi /etc/default/grub

기본적으로 GRUB_DEFAULT=0으로 되어 있는데, 기본으로 가장 상위 버전으로 부팅이 되는 것으로 생각하면 된다.

GRUB_DEFAULT="gnulinux-advanced-b7e9ad35-1a1f-45e3-9cfd-084a7ce27282>gnulinux-5.4.0-42-generic-advanced-b7e9ad35-1a1f-45e3-9cfd-084a7ce27282"

아래와 같이 변경한 내용을 grub에 적용해준다.

$ sudo update-grub
$ reboot

부팅 이후에 원하는 버전으로 부팅이 되었는지 확인해보자

$ uname -a
반응형
반응형

fstab 수정시 옵션을 설정할 수 있는데 보통 구글링하면 defaults로 설정되어 있다.

여기서 default로 "s"를 빼고 작성시 리부팅할때 fstab 비정상 동작으로 boot sequence가 중단될 수 있다.

이럴 경우 ssh daemon이 정상적으로 뜨지 않아서 데이터 센터 등에 서버가 있을 경우 난감한 상황이 발생할 수 있다.

 

처음 작성할 때에 defaults가 아닌 nofail로 설정할 경우, 해당 설정이 정상적이지 않더라도 mount를 비활성화하고 boot sequence를 계속하게 할 수 있다.

차라리 그냥 다른 이유에서도 mount가 비정상 상황이 발생하더라도 nofail로 boot seqence를 계속하도록 수정하는게 중요할 것 같다.

반응형
반응형

다음은 SSH 포트(기본 22번 포트)와 3000, 3001번 포트만 허용하고 나머지는 차단하는 iptables 명령어.

설정 명령어
SSH 포트를 먼저 허용 (기본적으로 22번 포트를 사용). 만약 SSH 포트를 변경했다면 해당 포트로 수정.

sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT

필요한 포트를 허용 (예: 3000번, 3001번 포트).

sudo iptables -A INPUT -p tcp --dport 3000 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 3001 -j ACCEPT

로컬호스트(127.0.0.1)에서 오는 트래픽은 허용.

sudo iptables -A INPUT -i lo -j ACCEPT

기본 정책을 설정하여 나머지 모든 입력 트래픽을 차단.

sudo iptables -P INPUT DROP

나가는 트래픽은 허용하려면 아래 명령을 추가.

sudo iptables -P OUTPUT ACCEPT

연결이 이미 허용된 세션(ESTABLISHED, RELATED)에 대해서는 계속 허용하도록 설정.

sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

이 설정을 완료하면 SSH(22번 포트), 3000번 포트, 3001번 포트만 허용되고 나머지 트래픽은 모두 차단.

설정 저장
Ubuntu에서는 iptables 설정이 서버 재부팅 후에도 유지되도록 저장해야 함.

iptables-persistent 패키지를 설치:

sudo apt install iptables-persistent

설정을 저장합니다:

sudo netfilter-persistent save

이제 iptables 설정이 시스템 재부팅 후에도 유지됨.

반응형
반응형

Ubuntu 22.04에서 기본적으로 제공되는 방화벽 도구는 UFW(Uncomplicated Firewall) 임 UFW는 간단한 명령어로 방화벽을 설정하고 관리할 수 있도록 도와주며, 아래는 UFW를 사용해 방화벽을 설정하는 방법임.

참고
SSH 연결 상태에서 진행시 default incoming deny rule이 먼저 적용시에 연결이 끊길경우 서버에 물리적으로 모니터 연결해서 붙어야함.
혹시 불안한 경우에는 아래와 같이 진행함.

SSH 포트 허용:

sudo ufw allow ssh

기본 정책 설정 (모든 들어오는 트래픽 차단):

sudo ufw default deny incoming

마지막으로 방화벽을 활성화:

sudo ufw enable

아래는 일반적인 설정 방법

  1. UFW 설치 확인
    일반적으로 UFW는 Ubuntu에 기본 설치되어 있지만, 설치되지 않은 경우에는 다음 명령어로 설치할 수 있음:
sudo apt update  
sudo apt install ufw  
  1. 방화벽 상태 확인
    현재 UFW가 활성화되어 있는지 확인:
sudo ufw status  

이 명령어를 실행하면 방화벽이 활성화되어 있는지, 어떤 규칙이 설정되어 있는지 알 수 있음.

  1. 기본 정책 설정
    UFW의 기본 정책을 설정함. 일반적으로 모든 들어오는 트래픽은 차단하고 나가는 트래픽은 허용하는 방식으로 설정함.
sudo ufw default deny incoming  
sudo ufw default allow outgoing  
  1. 특정 포트 허용하기
    자주 사용하는 서비스의 포트를 허용하려면 다음과 같이 설정함.

SSH 포트 (기본 22번 포트)를 허용:

sudo ufw allow ssh  

HTTP(80번 포트)와 HTTPS(443번 포트)를 허용:

sudo ufw allow http  
sudo ufw allow https  

특정 포트를 허용(ex. 8080 포트):

sudo ufw allow 8080  
  1. IP 주소 또는 네트워크 대역 허용
    특정 IP 주소나 네트워크 대역만 허용하려면 다음과 같이 설정.

특정 IP 주소에서 SSH 접속을 허용:

sudo ufw allow from 192.168.1.100 to any port 22  

특정 대역 (예: 192.168.1.0/24)에서 특정 포트를 허용:


sudo ufw allow from 192.168.1.0/24 to any port 80  
  1. UFW 활성화 및 비활성화
    방화벽을 활성화:
sudo ufw enable  

비활성화하려면:

sudo ufw disable  
  1. 방화벽 규칙 삭제
    잘못 설정된 규칙을 삭제하고 싶을 때는 delete 옵션을 사용.

ex) 8080 포트를 허용하는 규칙을 삭제:

sudo ufw delete allow 8080  
  1. 방화벽 로그 설정
    방화벽의 로그를 활성화:
sudo ufw logging on  

로그를 비활성화:

sudo ufw logging off  
  1. 전체 상태 확인
    설정한 방화벽 규칙을 다시 확인하려면 다음 명령어를 사용함.
sudo ufw status verbose  

이렇게 하면 방화벽의 상태와 함께 설정된 규칙들을 자세히 볼 수 있음.

반응형
반응형

포인트

  • 그냥 watch 사용시에는 어디가 바꼈는지 매번 눈으로 확인해야 하는데, 이것을 diff 명령어로 틀린 부분만 표시할 수 있음.
  • 색을 표시하는 부분은 색코드를 직접 이용할 수 있지만 watch 명령어와 사용시 색이 표시 되지 않고 색 코드가 그대로 노출되는 되기 때문에 일반적으로 output에 색코드를 직접 기입하는 대신에 tput을 이용하면 색을 표시할 수 있음

샘플 코드

#!/bin/bash

# temp file
LAST_OUTPUT="/tmp/last_df_output.txt"
NEW_OUTPUT="/tmp/new_df_output.txt"

# color supporting check
if [ -t 1 ]; then
    RED=$(tput setaf 1)
    RESET=$(tput sgr0)
else
    RED=""
    RESET=""
fi

# initial output 
df -h > "$LAST_OUTPUT"

while true; do
    # new output
    df -h > "$NEW_OUTPUT"

    if ! cmp -s "$NEW_OUTPUT" "$LAST_OUTPUT"; then
        clear
        # diff will be printed in red color
        diff --unchanged-line-format="%L" --old-line-format="" --new-line-format="${RED}%L${RESET}" "$LAST_OUTPUT" "$NEW_OUTPUT"
    fi

    # last output store
    mv "$NEW_OUTPUT" "$LAST_OUTPUT"

    # time interval
    sleep 1
done
반응형
반응형

Bash 스크립트에서 매번 if [ $? -ne 0 ];을 써서 명령어의 실행 결과를 확인하는 건 번거롭고 코드가 지저분해 보일 수 있다. 이를 깔끔하게 처리할 수 있는 몇 가지 방법을 소개한다.

  1. set -e 사용
    스크립트에 set -e를 추가하면, 명령어가 실패할 때(exit code가 0이 아닐 때) 자동으로 스크립트 실행이 중지된다. 이렇게 하면 매번 $?를 체크할 필요가 없어진다.
#!/bin/bash
set -e

# 명령어 실행 (실패하면 스크립트가 중지됨)

command\_1  
command\_2

echo "이 메시지는 위 명령어들이 성공한 경우에만 출력됨"  

set -e는 스크립트 실행을 중단해야 할 때 유용하지만, 모든 경우에 적합하지 않을 수 있다. 실패해도 계속 실행해야 하는 상황이라면 다른 방법을 고려하는 게 좋다.

  1. 함수로 처리
    자주 사용하는 에러 확인을 함수로 만들어 놓으면 매번 $?를 확인하는 중복을 줄일 수 있다.
#!/bin/bash

check\_command() {  
"$@"  
if \[ $? -ne 0 \]; then  
echo "Error: '$\*' 명령어가 실패했습니다." >&2  
exit 1  
fi  
}

check\_command ls /path/to/dir  
check\_command another\_command  

check_command 함수는 전달받은 명령어를 실행하고, 실패하면 에러 메시지를 출력한 뒤 스크립트를 종료하는 방식이다.

  1. 명령어 체인 (&&와 || 사용)
    명령어가 성공하거나 실패할 때 각각 다른 동작을 하고 싶다면 &&와 ||를 사용하는 것도 깔끔하다.
command && echo "성공" || echo "실패"  
&&는 명령어가 성공했을 때 실행되고, ||는 명령어가 실패했을 때 실행된다. 단순한 에러 처리를 할 때 유용하다.
  1. 트랩(Trap) 사용
    스크립트 전체에서 에러가 발생할 경우에 대한 공통 처리가 필요하다면 trap을 사용할 수 있다. 특정 상황이나 에러 발생 시 자동으로 호출되는 함수를 정의할 수 있다.
#!/bin/bash

trap 'echo "Error occurred at line $LINENO"; exit 1' ERR

# 명령어 실행

command\_1  
command\_2  

이 코드는 ERR 신호가 발생할 때, 즉 명령어가 실패하면 해당 트랩이 실행돼 에러 메시지를 출력하고 스크립트를 종료한다.

반응형

+ Recent posts