VEDA 주간 학습 정리
[7주차] 리눅스 기초와 Bash 스크립트 작성
이번 주 학습을 한 문장으로 정리하면: 컴퓨터가 프로그램을 실행하는 방식부터 유닉스 명령어, Bash 스크립트, 우분투 앱 설치 흐름까지 리눅스 사용의 기본기를 정리한 주간
작성일: 2026.05.10
이번 주 학습 목표
- 컴퓨터의 기본 구성과 프로세스가 실행되는 흐름 이해하기
- 유닉스 명령어와 파이프, 리디렉션을 이용해 원하는 정보를 찾고 저장하기
- Bash 변수, 조건문, 반복문, 배열, 함수를 이용해 간단한 자동화 스크립트 작성하기
- 우분투에서 apt, .deb, .tar 방식으로 앱을 설치하는 방법 정리하기
1. 컴퓨터의 작동 원리
이번 주 첫 번째 정리는 컴퓨터가 프로그램을 어떻게 실행하는지에 대한 내용이었다. 프로그램은 저장 장치에 파일 형태로 있다가 실행되면 RAM에 올라가고, CPU가 명령어를 해석하며 연산을 수행한다. 이때 레지스터는 CPU 내부의 아주 작고 빠른 임시 저장 공간으로 사용되고, 시스템 버스는 CPU와 메모리, 저장 장치가 데이터를 주고받는 통로 역할을 한다.
| 구성 요소 | 역할 | 핵심 정리 |
|---|---|---|
| CPU | 프로그램 명령어를 해석하고 산술, 논리 연산을 수행한다 | 컴퓨터의 두뇌 역할 |
| 레지스터 | CPU 내부에 있는 매우 빠른 메모리 | 연산 중 필요한 값을 잠깐 보관 |
| RAM | 실행 중인 프로그램 코드와 데이터를 저장한다 | 전원이 꺼지면 사라지는 휘발성 메모리 |
| 저장 장치 | SSD, HDD, 플래시 메모리처럼 데이터를 보관한다 | 전원이 꺼져도 데이터가 남는 비휘발성 저장소 |
| 시스템 버스 | 컴퓨터 내부 장치들이 데이터를 주고받는 통로 | CPU, 메모리, 입출력 장치를 연결 |
리눅스에서는 프로그램이 실행되면 프로세스가 된다. 커널이 부팅될 때 가장 먼저 만드는 프로세스는 PID 1번이며, 전통적으로 init 프로세스라고 부른다. 현재 많은 리눅스 배포판에서는 systemd가 이 초기화 프로세스 역할을 하며 서비스 실행, 로그, 자원 관리 등을 담당한다.
프로세스 종료 관련 개념
- 좀비 프로세스: 자식 프로세스가 종료되었지만 부모가 종료 상태를 회수하지 않아 완전히 정리되지 않은 상태
- 고아 프로세스: 부모 프로세스가 자식 프로세스보다 먼저 종료되어 남겨진 상태
- SIGCHLD: 자식 프로세스가 종료되었을 때 부모 프로세스에게 전달되는 시그널
프로세스 사이의 통신 방식도 함께 정리했다. 파이프는 한쪽 출력이 다른 쪽 입력으로 흘러가는 방식이고, 메시지 큐는 메시지 단위로 데이터를 주고받는다. 공유 메모리는 여러 프로세스가 같은 메모리 영역을 바라보기 때문에 빠르지만, 동시에 접근하면 데이터가 꼬일 수 있어 세마포어나 뮤텍스 같은 동기화 수단이 필요하다.
2. 유닉스 명령어
두 번째 주제는 터미널에서 자주 쓰는 유닉스 명령어였다. 핵심은 명령어 하나를 외우는 것보다, 명령어들을 파이프와 리디렉션으로 연결해 필요한 정보를 찾고 파일로 남기는 흐름을 익히는 것이다.
프로세스 확인과 종료
ps -ef | grep sleep
kill 1165
ps -p 1165
ps -ef: 모든 프로세스를 자세한 형식으로 출력한다.grep sleep: 출력 결과 중sleep이 포함된 줄만 찾는다.|: 앞 명령어의 출력을 뒤 명령어의 입력으로 넘긴다.kill PID: 해당 PID의 프로세스에 종료 요청을 보낸다.
텍스트 처리와 시스템 확인 명령어
| 명령어 | 주요 용도 | 예시 |
|---|---|---|
grep |
파일이나 출력에서 특정 문자열을 검색한다 | grep "error" log.txt |
wc |
줄 수, 단어 수, 바이트 수를 계산한다 | ls | wc -l |
tr |
문자를 치환하거나 삭제한다 | echo "hello" | tr 'a-z' 'A-Z' |
find |
조건에 맞는 파일을 디렉토리에서 검색한다 | find . -name "*.cpp" |
stat |
파일의 상세 정보와 타임스탬프를 확인한다 | stat main.cpp |
df |
전체 디스크 사용량을 확인한다 | df -h, df -i |
du |
특정 파일이나 디렉토리의 용량을 확인한다 | du -sh * |
tar |
여러 파일을 묶거나 압축을 해제한다 | tar -xzvf file.tar.gz |
read |
사용자 입력을 변수로 받는다 | read user_name |
리디렉션
리디렉션은 표준 입력과 표준 출력의 방향을 바꾸는 기능이다. 화면에 출력될 내용을 파일에 저장하거나, 파일 내용을 명령어의 입력으로 사용할 때 쓴다.
| 기호 | 의미 | 예시 |
|---|---|---|
> |
출력을 파일에 덮어쓴다 | ls > files.txt |
>> |
출력을 파일 끝에 추가한다 | echo "done" >> log.txt |
2> |
표준 에러만 파일로 저장한다 | command 2> error.log |
< |
파일 내용을 표준 입력으로 사용한다 | cat < info.txt |
3. Bash script 작성하기
세 번째 주제는 Bash script 작성이었다. 스크립트는 터미널에서 반복해서 입력하던 명령어를 텍스트 파일에 모아둔 것이다. 첫 줄에는 이 파일을 어떤 셸로 실행할지 알려주는 셰뱅 라인을 쓰고, 직접 실행하려면 chmod +x로 실행 권한을 부여해야 한다.
Bash 기본 문법
- 변수 선언은
name="value"처럼 쓰며,=앞뒤에 공백을 넣지 않는다. - 변수 사용은
$name또는${name}형태로 한다. - 산술 연산은
$(( ))형태를 사용하면 읽기 쉽다. - 작은따옴표는 값을 그대로 보존하고, 큰따옴표는 변수 치환을 허용한다.
- 조건문에서는
[ 조건 ]의 대괄호 안팎 공백을 지켜야 한다.
변수, 조건문, 반복문 예시
#!/bin/bash
name="VEDA"
count=3
if [ "$count" -gt 0 ]; then
echo "${name} 실습을 ${count}번 반복합니다."
fi
for i in 1 2 3; do
echo "practice ${i}"
done
배열과 함수 예시
#!/bin/bash
fruits=("apple" "banana" "cherry")
for fruit in "${fruits[@]}"; do
echo "I like ${fruit}"
done
greet() {
local user_name=$1
echo "Hello, ${user_name}!"
}
greet "Alice"
실습 예제: GGUF 파일로 Modelfile 만들기
이번 주 스크립트 예제는 현재 디렉토리에 있는 *.gguf 파일을 찾아 Modelfile을 자동으로 생성하는 것이다. 현재 작업 위치가 /Users/cwohk/models/Hyperclova이고, 그 안에 HyperCLOVAX-SEED-Omni-8B-Q4_K_M.gguf 파일이 있다고 가정한다.
생성되어야 하는 Modelfile 내용
FROM /Users/cwohk/models/Hyperclova/HyperCLOVAX-SEED-Omni-8B-Q4_K_M.gguf
#!/bin/bash
shopt -s nullglob
current_dir="$(pwd -P)"
models=("${current_dir}"/*.gguf)
if [ "${#models[@]}" -eq 0 ]; then
echo "현재 디렉토리에 .gguf 파일이 없습니다."
exit 1
fi
model_file="${models[0]}"
printf 'FROM %s\n' "$model_file" > Modelfile
echo "Modelfile 생성 완료"
cat Modelfile
shopt -s nullglob:*.gguf에 매칭되는 파일이 없을 때 패턴 문자열이 그대로 남지 않게 한다.pwd -P: 현재 디렉토리의 실제 절대 경로를 가져온다.models=("${current_dir}"/*.gguf): 현재 디렉토리의 GGUF 파일 목록을 배열에 담는다.printf와>: 원하는 문자열을Modelfile에 덮어쓴다.
4. 우분투 앱 설치하기
네 번째 주제는 우분투에서 앱을 설치하는 방법이었다. 우분투에서는 보통 APT 패키지 관리자를 먼저 사용하고, 공식 사이트에서 받은 .deb 파일이나 압축 아카이브인 .tar 파일을 사용하는 경우도 있다.
APT 패키지 관리자
sudo apt update
sudo apt upgrade -y
sudo apt install curl
sudo apt install git
sudo apt install vlc
sudo apt update: 로컬 패키지 인덱스를 최신 상태로 갱신한다.sudo apt upgrade -y: 설치된 패키지를 업그레이드한다.sudo apt install 패키지이름: 원하는 앱이나 도구를 설치한다.
패키지 검색과 정보 확인
apt search video player
apt show ffmpeg
apt list --installed
패키지 이름이 정확히 기억나지 않을 때는 apt search로 검색하고, 설치 전 상세 정보가 필요하면 apt show로 확인한다. 이미 설치된 패키지를 확인할 때는 apt list --installed를 사용할 수 있다.
.deb 파일 설치
sudo dpkg -i 파일이름.deb
sudo apt install -f
sudo apt install ./google-chrome-stable_current_amd64.deb
dpkg -i로 설치할 수도 있지만 의존성 오류가 날 수 있다. 그래서 sudo apt install ./파일이름.deb처럼 APT를 통해 로컬 .deb 파일을 설치하면 의존성을 함께 처리해줘서 더 편리하다.
.tar 파일 설치
tar -xzvf 파일이름.tar.gz
tar -xjvf 파일이름.tar.bz2
tar -xJvf 파일이름.tar.xz
cd 폴더이름
./configure
make
sudo make install
설치 방식 정리
- 가능하면 APT로 설치하는 것이 업데이트와 의존성 관리에 가장 편하다.
- 공식 사이트에서 받은
.deb파일은apt install ./파일명.deb방식이 편리하다. .tar파일은 압축 해제 후 직접 실행하거나 빌드해야 하므로 자동 업데이트가 어렵다.
마무리
이번 주는 리눅스 환경을 사용하는 데 필요한 기본기를 넓게 정리한 시간이었다. 컴퓨터가 프로그램을 실행하는 구조를 먼저 보고, 그 위에서 프로세스와 명령어가 어떻게 동작하는지 확인했다.
특히 Bash script 작성은 유닉스 명령어와 리디렉션을 실제 자동화로 연결하는 부분이라 중요했다. 단순한 명령어 사용을 넘어, 반복되는 작업을 스크립트로 만들 수 있다는 점이 이번 주 학습의 가장 실용적인 포인트였다.