패키지 설치 Overview
패키지
- 프로그램 설치 후 바로 실행할 수 있는 설치 파일
- 확장명은 *.deb
- kr.archive.ubuntu.com/ubuntu/pool
dpkg
- 우분투에서 패키지(프로그램)를 설치할 때 많이 사용되던 명령어
- apt-get이 나오기 전에 주로 씀
apt-get
- dpkg의 확장 개념
- dpkg 기능이 포함되어 있음
의존성이 있는 deb 파일 다운로드 및 설치하기
- 의존성 문제를 해결하기 위해 다른 패키지를 설치하고 싶지만 패키지를 설치하기 전 어떤 deb 파일을 설치해야 하는지 정확히 알 수 X
- 설치해야 할 deb 파일을 알아내더라도 그 파일 또한 의존성 문제가 있을 수 있음
- 우분투에서는 이러한 문제를 한번에 해결하기 위해 apt-get 명령어 제공
apt-get 명령어
- apt-get 명령어는 *.deb 패키지를 설치하는 편리한 도구
- 우분투가 제공하는 deb 파일 저장소에서 자동으로 deb 파일을 다운로드하여 설치
- 의존성 문제를 걱정하지 않아도 됨
- dpkg 명령어의 경우, *.deb 파일을 다운로드한 후 설치해야 하는 번거로움이 있음
main, universe, restricted, multiverse의 의미
- main: 우분투에서 공식적으로 지원하는 무료 소프트웨어
- universe: 우분투에서 지원하지 않는 무료 소프트웨어
- restricted: 우분투에서 공식적으로 지원하는 유료 소프트웨어
- multiverse: 우분투에서 지원하지 않는 유료 소프트웨어
미러(mirror) 사이트
- 우분투 패키지 저장소는 우분투 사이트에서 제공
- 전 세계적으로 동일한 저장소가 수백 개 존재
- 대학, 연구소, 기업 등이 자발적으로 구축한 것
- apt-get -y install 패키지명 : sources.list에 기록된 사이트에 자동으로 접속해서 다운로드 가능
apt 패키지 관련 명령어
apt-cache [옵션] [서브 명령] : 패키지 검색 및 정보보기 명령 (패키지 데이터베이스(APT 캐시)에서 패키지와 관련된 정보를 출력)
옵션
-f : 패키지에 대한 전체 정보 출력
-h : 관련 도움말 출력
서브
stats : 캐시 통계 정보(전체 패키지 이름과 단일 가상 패키지 등) 출력
dump : 현재 설치되어 있는 패키지 업그레이드
pkgnames : 사용 가능한 모든 패키지의 이름 출력
search [키워드] : 키워드에 해당하는 패키지 검색
show [패키지 이름] : 해당 패키지의 정보 출력
showpkg [패키지 이름] : 패키지의 의존성과 역의존성에 대한 정보 출력
APT 캐시 통계정보 출력 : apt-cache stats
- 시스템에 설치되어 있는 전체 패키지의 이름과 일반 패키지
- 순수 가상과 단일 가상 및 혼합 가상 패키지
- 등의 APT 캐시의 전반적인 통계정보를 출력하는 명령
패키지 업데이트 : apt-cache dump
- 현재 시스템에 설치되어 있는 모든 패키지에 대한 업데이트 수행
모든 패키지 이름 출력 : apt-cache pkgnames
- 현재 시스템에 설치되어 있는 모든 패키지의 이름 출력
패키지 정보 출력 : apt-cache show [패키지명]
- 현재 시스템에 설치되어 있는 특정 패키지의 정보 출력
apt-get [옵션] [서브 명령] : 패키지 설치 및 업데이트 명령
옵션
-d : 패키지 다운로드 수행
-f : 의존성이 깨진 패키지 수정
-h : 관련 도움말 출력
서브 명령
update : 패키지 저장소에서 새로운 패키지 정보를 가져옴
upgrade : 모든 패키지를 최신 버전으로 업그레이드
install [패키지 이름] : 해당 패키지 설치
remove [패키지 이름] : 설치된 해당 패키지 제거
purge [패키지 이름] : 설치된 해당 패키지와 설정 파일을 모두 삭제
autoremove : 시스템에 설치된 패키지를 자동으로 정리 및 삭제
download [패키지 이름] : 해당 패키지를 현재 디렉터리에 다운로드
autoclean : 오래된 패키지 또는 불완전한 다운로드 패키지 제거
check : 의존성이 깨진 패키지 확인
clean : /var/cache/apt/archives 디렉터리에 캐시되어 있는 모든 패키지를 제거하여 디스크 공간 확보
패키지 정보 업데이트 : sudo apt-get update
- update 서브 명령을 수행하면 /etc/apt/sources.list에 새로운 패키지 정보(목록)를 가져와서
- 만약 /etc/apt/sources.list 파일을 수정하였다면 반드시 이 명령 수행해야 함
패키지 업그레이드 : sudo apt-get upgrade
- 현재 시스템에 설치되어 있는 모든 패키지 중에서 업그레이드가 필요한 패키지를 찾은 다음 새로운 버전이 있는 패키지에 대해서는 모두 업그레이드를 수행
- 업그레이드 필요여부 검색 : sudo apt-get upgrade | grep [패키지 이름]
- 검색과정 멈춤 : Ctrl+C 누르기
특정 패키지 설치 또는 업그레이드 : sudo apt-get install
- 1개 또는 1개 이상의 패키지를 설치하거나 업그레이드 수행
- 1개의 패키지만 설치할 경우 : sudo apt-get install [패키지 이름]
- 패키지를 설치할 때 진행여부에 대한 y를 입력하지 않아도 자동으로 입력되도록 수행하려면 -y 옵션 사용 sudo apt-get -y install [패키지 이름]
- 여러 패키지 설치할 경우 : sudo apt-get install [패키지 이름1] [패키지 이름2]
- 새로운 패키지를 설치하지 않고 업그레이드만 수행 : sudo apt-get install [패키지 이름] --only-upgrade
특정 패키지 삭제 : purge 또는 remove
remove: 해당 패키지의 설정 파일은 남아있게 됨
purge: 남은 설정 파일까지 모두 삭제
설정 파일을 남겨놓는 이유: 나중에 동일한 패키지를 다시 설치할 때 재사용
sudo apt-get purge [패키지 이름]
sudo apt-get remove [패키지 이름] --purge (두 옵션을 함께 쓸 수 있음)
패키지 자동 정리 및 삭제 : autoremove
더 이상 존재할 필요가 없는 패키지가 남아있을 수 있으므로 잔존해 있는 패키지에 대해서 자동 정리 및 삭제
sudo apt-get autoremove
디스크 공간 정리 : clean
패키지를 검색하였거나 다운로드한 파일들을 삭제한 후 디스크 공간 정리
sudo apt-get clean
특정 패키지 다운로드 : download
특정 패키지를 직접 설치하지 않고 다운로드만 수행
sudo apt-get download [패키지 이름]
특정 패키지의 소스 관련 서브 명령 : source
특정 패키지의 소스 코드가 필요할 경우 다운로드할 때 사용
sudo apt-get --download-only source [패키지 이름]
다운로드를 수행한 특정 패키지의 소스코드에 대한 압축 해제 : sudo apt-get source [패키지 이름]
특정 패키지의 소스 코드 다운로드를 수행하여 압축을 해제하고 컴파일 : sudo apt-get --compile source [패키지 이름]
문제 11-01
- pkgnames 서브 명령으로 모든 패키지 이름 출력하기
- upgrade 서브 명령으로 업그레이드를 수행할 패키지 확인하기
- install 서브 명령과 옵션 y를 설정하여 netcat 패키지 설치하기
- 설치된 netcat 패키지의 정보 출력하기
- netcat 패키지의 설정 파일까지 모두 삭제하기
$ sudo apt-cache pkgnames
$ sudo apt-get upgrade
$ sudo apt-get -y install netcat
$ sudo apt-cache show netcat
$ sudo apt-get purge netcat
DPKG 패키지 관련 명령어
DPKG 명령
- 시스템의 특정 파일이 어느 패키지에 포함되어 있는지 등에 대한 구체적인 기능을 확인할 때 옵션과 함께 사용
- APT 명령은 소프트웨어 관리를 위해 내부적으로 DPKG 명령을 이용
dpkg [옵션] [패키지 이름 또는 파일 이름] : 패키지 관리 명령
옵션
-l : 설치된 패키지 목록 전체 출력
-l [패키지 이름] : 해당 패키지의 설치상태 정보 출력
-r [패키지 이름] : sudo 명령을 사용하여 해당 패키지를 삭제
-P [패키지 이름] : sudo 명령을 사용하여 해당 패키지와 설정 정보 모두 삭제
-s [패키지 이름] : 해당 패키지의 자세한 정보 출력
-L [패키지 이름] : 해당 패키지가 설치된 파일목록 출력
-S [경로명] : 경로명이 포함된 패키지 검색
-c [.파일 확장자] : 해당 파일 확장자를 가진 파일의 내용 출력
-i [.파일 확장자] : sudo 명령으로 해당 파일 확장자를 가진 파일 설치
-x [.파일 확장자] [디렉터리명] : 해당 파일 확장자를 가진 파일을 지정한 디렉터리에 풀어놓음
dpkg -l : 시스템에 설치되어 있는 패키지의 목록 출력
dpkg -l zip : 설치된 패키지 중에서 zip 패키지에 대한 정보만 출력
dpkg -l gnome-chess : gnome-chess 패키지가 설치되어 있는지 확인
sudo apt-get download gnome-chess
ls gnome* : 다운로드한 패키지 확인
sudo dpkg -i gnome-chess_1%3a3.36.0-1_amd64.deb : 의존성 패키지 hoichess가 설치되어 있지 않으므로 설치가 정상적으로 안됨
sudo apt-get install hoichess : gnome-chess 패키지의 의존성을 가진 hoichess 패키지 설치
특정 패키지를 못 찾는다는 오류 메시지가 출력되면 해당 패키지는 제외하고 설치 진행
APTITUDE 패키지 관련 명령어
APTITUDE 명령 : sudo 명령으로 root 계정 권한 위임
- apt 명령과 같이 패키지 관리를 쉽게 작업할 수 있도록 자동화 기능 제공
aptitude [서브 명령] : 패키지 설치 및 업데이트 명령
서브
단독 실행 : 비주얼 모드로 실행하기 위한 curses 프로그램 활성화
update : 패키지 저장소에서 새로운 패키지 정보를 가져옴
upgrade : 모든 패키지를 최신 버전으로 업그레이드
install [패키지 이름] : 해당 패키지 설치
remove [패키지 이름] : 설치된 해당 패키지 제거
purge [패키지 이름] : 설치된 해당 패키지와 설정 파일을 모두 삭제
autoremove : 시스템에 설치된 패키지를 자동으로 정리 및 삭제
download [패키지 이름] : 해당 패키지를 현재 디렉터리에 다운로드
autoclean : 오래된 패키지 또는 불완전한 다운로드 패키지 제거
check : 의존성이 깨진 패키지 확인
clean : /var/cache/apt/archives 디렉터리에 캐시되어 있는 모든 패키지를 제거하여 디스크 공간 확보
sudo apt-get install aptitude : aptitude 패키지 설치
sudo aptitude update : 기존에 설치된 패키지의 새로운 정보를 가져와서 apt 캐시를 수정
aptitude search gnome : gnome으로 시작하는 패키지 검색
aptitude show gnome-clock : gnome-clocks 패키지의 상세한 정보 확인
sudo aptitude install gnome-clocks : gnome-clocks 패키지 설치
문제 11-02
- aptitude 명령으로 gnome-dictionary 패키지에 대한 상세한 정보 확인하기
- aptitude 명령으로 gnome-dictionary 패키지 설치하기
- apt 명령으로 gnome-dictionary 패키지가 설치한 파일목록 확인하기
- gnome-dictionary 패키지를 실행하기
- 우분투 소프트웨어 센터를 통해 OpenTTD 게임 설치하기
$ aptitude show gnome-dictionary
$ sudo aptitude install gnome-dictionary
$ sudo apt-cache show gnome-dictionary
> 윈도 화면에 설치된 패키지 아이콘을 클릭하여 실행
> 우분투 소프트웨어 센터에서 OpenTTD 게임 설치
파일 아카이브와 압축
파일 아카이브
- 아카이브(Archive)란 특정 시간에 함께 묶인 파일이나 디렉터리의 집합을 의미 (저장소 또는 보관소)
- 다른 시스템과 파일이나 디렉터리를 주고 받거나 파일을 백업하는 용도로 사용
- 파일 아카이브를 위해 사용되는 명령은 tar, cpio, ar 등이 있음
tar 기능[옵션] [아카이브 생성 파일명] 대상 파일명 : 파일과 디렉터리를 묶어 하나의 아카이브로 생성하는 명령
기능
c : 새로운 tar 아카이브 생성
r : 새로운 파일 추가
t : tar 파일에 존재하는 파일 리스트 출력
u : 수정된 파일에 대해 업데이트 수행
x : tar 파일에 있는 원본 파일을 추출
옵션
C [디렉터리명] : 파일들을 특정 디렉터리에 풀어 놓음
f [디바이스명 또는 파일명] : 아카이브 파일 또는 테이프 장치를 지정
(디바이스명을 -으로 지정하면 tar 파일 대신 표준입력에서 읽어 들임)
h : 심볼릭 링크의 원본 파일 포함
j : bzip2로 압축 또는 해제
p : 파일 복구 시 원래의 접근 권한을 유지
v : 처리하고 있는 파일의 정보 출력
z : gzip으로 압축 또는 해제
Z : compress를 통해 아카이브를 필터링
아카이브 생성 : cvf
mkdir arch_test
cd arch_test
mkdir ex_ac.d
touch test_01.txt test_02.txt
gedit test_01.txt
gedit test_02.txt
cd ~
ls arch_test
tar cvf arch_test.tar arch_test
→ 기존에 존재하던 arch_test 디렉터리는 삭제되지 않고 그대로 남아있음
아카이브 내용 출력 : tvf
tar tvf arch_test.tar : 앞서 생성한 arch_test.tar 파일에 대한 상세한 정보 출력
아카이브 풀기 : xvf
이미 존재하는 아카이브 파일을 풀기 위함
cp arch_test.tar arch_test/ex_ac.d : arch_test.tar 아카이브를 arch_test/ex_ac.d 디렉터리에 복사
cd arch_test/ex_ac.d
tar xvf arch_test.tar
아카이브 업데이트 : uvf
이미 존재하는 아카이브 파일에 수정된 파일을 추가할 수 있음
u 기능은 아카이브에 존재하는 파일의 내용이 수정될 경우 아카이브를 업데이트하기 위해 사용하는 기능 (기존 파일의 내용에 변경 사항이 없다면 아카이브 파일에 아무런 변화 X)
cd ~
tar uvf arch_test.tar arch_test
gedit arch_test/test_01.txt
tar uvf arch_test.tar arch_test
아카이브에 파일 추가 : rvf
이미 존재하는 아카이브에 지정한 파일을 무조건 추가
tar rvf arch_test.tar hosts : 복사한 hosts 파일을 아카이브에 추가
아카이브와 파일 압축
아카이브를 생성하면서 파일 압축을 수행 (디스크 공간이 부족할 때 유용)
tar cvzf arch_test.tar.gz arch_test : arch_test 디렉터리를 아카이브 생성과 동시에 압축 파일로 생성
아카이브 생성과 동시에 bzip2 형식으로 파일 압축
tar cvjf arch_test.tar.bz2 arch_test
cf. 확장자 이름을 붙이는 것은 쉽게 알아보기 위한 것임 (필수로 붙여야 하는 것 X)
파일 압축과 해제
1) gzip 명령으로 파일 압축
gzip [옵션] 파일 이름 : gzip 형식으로 파일 압축 명령
옵션
-d : 파일 압축 해제
-l : 압축된 파일의 정보 출력
-r : 하위 디렉터리로 이동하여 파일 압축
-t : 압축 파일 검사
-v : 압축 정보를 화면에 출력
-9 : 최대한 압축
gzip arch_test.tar arch_test : arch_test 디렉터리를 arch_test.tar 파일명으로 압축 수행
→ arch_test.tar 파일은 사라지고 arch_test.tar.gz 압축 파일이 새로 생성됨 arch_test는 디렉터리이므로 무시됨
압축 파일 내용 보기 : zcat
zcat arch_test.tar.gz | more
cf. more은 페이지 단위, less는 줄 단위
압축 파일 풀기 : gunzip
gzip 명령으로 압축된 파일은 gunzip 명령으로 복원할 수 있으며 옵션 -d를 사용하여 압축된 파일을 복원할 수도 있음
gunzip arch_test.tar.gz
2) bzip2 명령으로 압축
bzip2는 gzip 명령에 비해 압축률은 좋지만 속도가 약간 느림
bzip2 [옵션] 파일 이름 : bzip2 형식으로 파일 압축 명령
옵션
-d : 파일 압축 해제
-l : 압축된 파일의 정보 출력
-t : 압축 파일 검사
-v : 압축 정보를 화면에 출력
-best : 최대한 압축
bzip2 arch_test.tar arch_test
압축 파일 내용 보기 : bzcat
bzcat arch_test.tar.bz2 | more
압축 파일 풀기 : bunzip2
bunzip2 arch_test.tar.bz2
tar cvf my.tar /etc/fonts/ -- 묶기
tar cvJf my.tar.xz /etc/fonts/ -- 묶기+xz로 압축
tar cvzf my.tar.gz /etc/fonts/ -- 묶기+gzip로 압축
tar cvjf my.tar.bz2 /etc/fonts/ -- 묶기+bzip2로 압축
tar tvf my.tar -- 파일 확인
tar xvf my.tar -- tar 풀기
tar Cxvf newdir my.tar -- newdir에 tar 풀기
tar xJf my.tar.xz -- xz 압축 풀기+tar 풀기
tar xzf my.tar.gz -- gzip 압축 풀기+tar 풀기
tar xjf my.tar.bz2 -- bzip2 압축 풀기+tar 풀기
파일 아카이브와 압축 해보기
tar 아카이브를 현재 디렉터리에 풀기
- tar xvf T.tar
tar 아카이브를 지정된 디렉터리에 풀기
- tar xvf T.tar -C ./test
tar 아카이브의 내용 확인하기
- tar tvf T.tar
현재 디렉터리를 tar로 묶고 gzip으로 압축하기
- tar cvzf T.tar.gz *
gzip으로 압축된 tar 아카이브를 현재 디렉터리에 풀기
- tar xvzf T.tar.gz
현재 디렉터리를 tar로 묶고 bzip2로 압축하기
- tar cvjf T.tar.bz2 *
bzip2로 압축된 tar 아카이브를 현재 디렉터리에 풀기
- tar xvjf T.tar.bz2
문제 11-03
- 새로운 zip_test.d 디렉터리 생성하기
- zip_test.d 디렉터리로 이동하기
- touch 명령으로 ex_01.txt와 ex_02.txt 파일 생성하기
- gedit 창에서 ex_01.txt와 ex_02.txt 파일에 간단한 내용 각각 편집하기
- cd ~ 명령으로 사용자 계정의 홈 디렉터리로 이동하기
- tar 명령으로 zip_test.d 디렉터리를 대상으로 아카이브 ac_zip.tar 생성하기
- 아카이브 ac_zip.tar의 내용 확인하기
- ac_zip.tar 아카이브 풀기
$ mkdir zip_test.d
$ cd zip_test.d
$ touch ex_01.txt ex_02.txt
$ gedit ex_01.txt
$ gedit ex_02.txt
$ cd ~
$ tar cvf ac_zip.tar zip_test.d
$ tar tvf ac_zip.tar
$ tar xvf ac_zip.tar
소프트웨어 컴파일
컴파일러의 개념 (광의의 개념)
- 자연어로 작성된 고급언어를 컴퓨터가 이해할 수 있는 기계어로 번역해 주는 SW
- 자연어를 기계어로 번역해 주는 과정을 컴파일(Compile)이라고 함
gcc 컴파일러
- 우분투에서 사용하는 C언어 기본 컴파일러는 gcc
- 관련 패키지가 설치되어 있지 않으면 패키지를 설치하기
aptitude show gcc : aptitude 명령으로 gcc 패키지가 설치되어 있는지 확인
sudo apt-get install gcc : gcc 패키지가 설치 안되어있을 때 패키지 설치
gcc 컴파일러 사용
실행 파일의 이름을 사용자가 지정하지 않으면 기본적으로 a.out 파일명으로 생성됨
현재 디렉터리의 경로를 지정하기 위해 ./를 사용하여 ./a.out 명령으로 실행
gcc -o [변경할 실행파일명] [C 프로그램 소스 파일명]
geany 에디터 설치
sudo apt-get install geany
sudo apt-get install geany-plugins
geany 컴파일러 사용
-c : 링킹 전단계까지 오브젝트 파일을 만들어놓은 상태 (? 확실 X)
컴파일 → 빌드 → 실행
**void qsort(void *base, size_t nmemb, size_t size, int (*compare)(const void , const void ));
- #include <stdlib.h>에 정의된 quick sort 알고리즘 라이브러리 함수
- base: 정렬할 배열의 시작 주소
- nmemb: 배열 요소의 개수
- size: 배열의 한 요소당 크기 (bytes 단위)
- compare: 비교 함수의 포인터
**int compare(const void a, const void b)
- 반환값에 따라 요소들의 순서를 결정
- 비교 함수는 두 void * 포인터를 받아 정수로 캐스팅 후 값을 비교
| 반환값 | 의미 | 정렬 결과 |
| < 0 | a가 b보다 작다 | a가 b보다 앞에 온다 |
| == 0 | a와 b가 같다 | 순서 유지 (stable 아님) |
| > 0 | a가 b보다 크다 | a가 b보다 뒤에 온다 |
stable: 순서를 보장하는 것
코딩 실습
예제) qsort_example.c
#include <stdio.h>
#include <stdlib.h>
// 오름차순 비교 함수
int compare(const void *a, const void *b) {
return (*(int*)a - *(int*)b);
}
int main() {
int arr[] = {7, 2, 9, 4, 3, 8, 1};
int n = sizeof(arr)/sizeof(arr[0]);
printf("정렬 전 배열: ");
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\\n");
qsort(arr, n, sizeof(int), compare);
printf("정렬 후 배열: ");
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\\n");
return 0;
}
cf. (int)a : dereferencing
문제 설명
문자열 배열이 주어졌을 때, 다음 기준에 따라 정렬하여 출력하시오.
- 문자열 길이가 짧은 순서대로 정렬한다.
- 길이가 같다면 사전 순으로 앞선 문자열이 먼저 오도록 정렬한다.
입력
- 첫 줄에 정렬할 문자열의 개수 N이 주어진다. (1≤N≤100)
- 이후 N개의 줄에 문자열이 한 줄에 하나씩 주어진다.
- 문자열은 알파벳 소문자로만 구성되며, 길이는 최대 100자이다.
출력
- 정렬된 결과를 한 줄에 하나씩 출력한다.
입력 예시:
5
apple
kiwi
banana
pear
grape
출력 예시:
kiwi
pear
apple
grape
banana
답)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 100
#define MAX_LEN 101
// 문자열 비교 함수
int compare(const void *a, const void *b) {
const char *str1 = *(const char **)a;
const char *str2 = *(const char **)b;
int len1 = strlen(str1);
int len2 = strlen(str2);
if (len1 != len2) {
return len1 - len2;
} else {
return strcmp(str1, str2);
}
}
int main() {
int N;
char *words[MAX];
scanf("%d", &N);
getchar(); // 개행 문자 제거
for (int i = 0; i < N; i++) {
words[i] = malloc(MAX_LEN * sizeof(char)); // 동적 할당
fgets(words[i], MAX_LEN, stdin);
words[i][strcspn(words[i], "\\n")] = '\\0'; // 개행 제거
}
qsort(words, N, sizeof(char *), compare);
for (int i = 0; i < N; i++) {
printf("%s\\n", words[i]);
free(words[i]);
}
return 0;
}
words[i][strcspn(words[i], "\n")] = '\0';
- 널 문자를 넣어서 문자열을 끝내야 하는데 “\0” 를 쓰면 널 문자를 가리키는 포인터로 해석될 수 있기 때문에 작은 따옴표로 써야 함
'공부 기록 > 리눅스 기초' 카테고리의 다른 글
| [리눅스 기초] 12 쉘 스크립트(셸 스크립트) (1) (1) | 2026.01.17 |
|---|---|
| [리눅스 기초] 10 프로세스 관리 (0) | 2026.01.17 |
| [리눅스 기초] 09 프로세스 관리 (0) | 2025.11.03 |
| [리눅스 기초] 08 관리자 권한 실행 (0) | 2025.11.03 |
| [리눅스 기초] 07 파일 접근 권한 설정 (0) | 2025.11.02 |