poll, select, epoll관 관련한 다중 입출력의 내용과 더 많은 정보와 예제를 담은 리눅스 교재를 배포했습니다. 아래의 페이지에서 리눅스 교재를 받아가세요.

https://reakwon.tistory.com/233

 

리눅스 프로그래밍 note 배포

티스토리에 리눅스에 관한 내용을 두서없이 여지껏 포스팅했었데요. 저도 제 포스팅을 찾기가 어렵기도 하고 티스토리에서 코드삽입을 하게 되면 이게 일자로 쭉 쓰여져있는 x같은 현상이 생겨

reakwon.tistory.com

 

poll

select와 비슷한 함수입니다. 여러 file descriptor에 대해서 I/O를 수행하기 위한 준비가 될 때까지 기다리는 함수입니다. 여러 file descriptor를 감시하여 event가 발생할 때까지 기다린다고 보시면 됩니다.

예를 들어서 어떠한 서버가 여러 클라이언트에 대해서 연결을 갖게 되고, 입력을 처리하여야한다면 어떻게 해야할까요? 한가지 방법으로는 클라이언트 요청이 들어오면 쓰레드를 만들어서 따로 처리해줄 수 있죠. 그런데 이때 한계가 있습니다. 클라이언트의 요청이 많아질 경우에는 쓰레드를 그만큼 생성해야하는 문제가 있죠. 만약 client가 100개가 현재 연결되어 있는 서버에서는 100개의 쓰레드를 생성할 수는 없겠죠. 이보다는 100개의 socket에 대해서 지켜보다가 하나의 socket에 읽을 데이터가 생겼다면 그 socket에서 read를 하고 처리를 하면 되는 것이죠.

이 목적을 달성할 수 있는 함수가 poll입니다. poll은 여러 file descriptor에 대해서 이벤트가 발생하기를 기다렸다가, event가 발생하면 그에 대한 정보를 제공해줍니다. select와는 비슷한데, 더 섬세하게 다룰 수 있습니다. 먼저 함수의 원형을 봅시다.

 

함수 설명

int poll(struct pollfd *fds, nfds_t nfds, int timeout);

 - fds : pollfd의 구조체 포인터입니다. pollfd는 아래와 같이 선언되어 있습니다. 

struct pollfd {
   int   fd;         /* file descriptor */
   short events;     /* requested events */
   short revents;    /* returned events */
};

        fd : 점검할 file descriptor입니다. 

         events : fd에 대해서 주시할 event입니다. 이 event들은 OR(|)로 여러 가지를 줄 수 있습니다. event에 대해서는 아래 표에 설명해놓았습니다. 사용자가 설정합니다.

         revents : fd에 발생한 event를 의미합니다. 이는 사용자가 설정하는게 아니라 kernel이 설정해줍니다. 이 revents를 보고 어떤 event가 발생했는지 확인할 수 있습니다.

아래의 표를 보면 revents에는 모든 event가 설정이 되어질 수 있습니다. 하지만 events에는 아래의 3개는 설정할 수 없죠.

 

event 이름 event에 설정 가능 kernel이 revents에 설정 설명
POLLIN O O high priority 외의 자료를 바로 읽을 수 있음
(POLLRDNORM | POLLRDBAND와 동일)
POLLRDNORM O O 보통 자료를 바로 읽을 수 있음
POLLRDBAND O O 우선 순위 자료를 바로 읽을 수 있음
POLLPRI O O high priority 자료를 바로 읽을 수 있음
POLLOUT O O 보통의 자료를 쓸 수 있음
POLLWRNORM O O 보통의 자료를 쓸 수 있음
POLLWRBAND O O 우선 순위 자료를 바로 기록 할 수 있음
POLLERR   O 오류 발생
POLLHUP   O 연결 끊어짐
POLLNVAL   O fd가 열린 파일이 아님

 

- nfds : fds 배열의 크기를 의미합니다.

- timeout : poll이 대기할 시간을 설정할 수 있습니다. 여기서 단위는 ms이므로 1초만 대기하려면 timeout은 1000값이 되어야합니다. 이외에 0이거나 -1인 경우는 아래와 같습니다.

timeout == -1 : 무한정 기다립니다.

timeout == 0 : 전혀 기다리지 않습니다.

 

이를 이용해서 지난 select와 같은 역할을 하는 서버를 만들어보도록 합시다. 역시 네트워크에 대한 내용은 뺐습니다. 순수하게 poll이 어떻게 동작하는지만 확인할 것입니다. 그런데 한가지 알아두셔야할 것은 select와 마찬가지로 정규 파일에 대해서 사용하는 것은 적절하지 않다는 점은 알아두셔야합니다.  

//multiIO_poll.c 

#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <poll.h>

#define FD_SIZE 3
#define BUF_SIZE 128

int main(int argc, char *argv[]){
        char buf[BUF_SIZE];
        struct pollfd fdarr[FD_SIZE];
        int n, i, ret, end_count = 0;

        //3개의 파일의 이름을 받는다.
        if(argc != 4){
                printf("usage : %s file1 file2 file3\n", argv[0]);
                return 0;
        }


        for(i = 0; i < FD_SIZE; i++){
                int fd = open(argv[i+1],O_RDONLY);
                if(fd >= 0){
                        fdarr[i].fd = fd;
                        //차단없이 읽는 것을 주시할 event로 넣는다.
                        fdarr[i].events = POLLIN;
                }
        }

        while(1){

                memset(buf, 0x00, BUF_SIZE);

                // timeout == -1은 지정된 파일 서술자중
                // 하나라도 준비될때까지 무한정 기다린다.
                ret = poll(fdarr, FD_SIZE, -1);

                if(ret == -1){
                        perror("poll error ");
                        exit(0);
                }

                for(i = 0; i < FD_SIZE; i++){
                        //파일 디스크립터가 -1이면 볼 필요 없음.
                        //받은 이벤트인 revents에 POLLIN이 있다면
                        if(fdarr[i].fd != -1 && fdarr[i].revents & POLLIN){
                                while((n = read(fdarr[i].fd, buf, BUF_SIZE)) > 0){

                                        //quit가 들어오면 fdarr[i] read 종료
                                        if(!strcmp(buf,"quit\n")){

                                                //파일디스크립터 close
                                                close(fdarr[i].fd);
                                                //안쓰는 fd로 업데이트하기 위해 -1 지정
                                                fdarr[i].fd = -1;
                                                end_count++;
                                                if(end_count == FD_SIZE) 
                                                        exit(0);
                                                continue;
                                        }

                                        printf("fd[%d] - %s",fdarr[i].fd, buf);
                                }
                        }
                }

        }
        return 0;
}

 

역시 테스트하기 위해서는 클라이언트 프로그램이 필요합니다. 여기서는 select에서 설명했던 클라이언트 역할을 할  소스 코드 fwrite.c를 그대로 사용합니다.

https://reakwon.tistory.com/117

 

[리눅스] 다중입출력 - select개념과 설명과 예제

다중입출력 아래와 같은 상황을 생각해볼까요? 어떤 프로세스가 다음과 같이 파일 3개를 처리하는데 그 중 입력이 있는 파일을 프로세스에 처리하는 상황을 어떻게 구현할 수 있을까요? 이때 우

reakwon.tistory.com

역시 테스트 하기 위해서는 a, b, c라는 파일 3개를 새로 만들고 시작합시다. 그리고 fwrite.c와 multiIO_poll.c는 아래와 같이 컴파일 하시구요. 

# gcc multiIO_poll.c 
# gcc fwrite.c -o fwrite

 

자, 테스트할 준비는 이제 완료되었고, 아래와 같은 결과를 보입니다. 

./a.out a b c
# ./a.out a b c
fd[3] - hello, ifd[3] - 'm writifd[3] - ng file fd[3] - a
fd[4] - hello, ifd[4] - 'm writifd[4] - ng file fd[4] - b~~
fd[5] - hello, ifd[5] - 'm writifd[5] - ng file fd[5] - c..
fd[3] - bye pollfd[3] - 
fd[4] - bye! 
fd[5] - i have tfd[5] - o go nowfd[5] -
./fwrite a ./fwrite b ./fwrite c
# ./fwrite a
hello, i'm writing file a
bye poll
quit
# ./fwrite b
hello, i'm writing file b~~
bye! 
quit 
# ./fwrite c
hello, i'm writing file c..
i have to go now 
quit 

 

역시나 poll은 정규 파일에 대해서 항상 준비되어있다고 판단하기 때문에 루프에다가 로그 printf를 찍어보면 엄청나게 바쁜 루프를 도는 것을 확인할 수 있습니다. 

반응형
블로그 이미지

REAKWON

와나진짜

,

systemd 뿐만 아니라 데몬의 특징을 담은 더 많은 정보와 예제를 담은 리눅스 교재를 배포했습니다. 아래의 페이지에서 리눅스 교재를 받아가세요.

https://reakwon.tistory.com/233

 

리눅스 프로그래밍 note 배포

티스토리에 리눅스에 관한 내용을 두서없이 여지껏 포스팅했었데요. 저도 제 포스팅을 찾기가 어렵기도 하고 티스토리에서 코드삽입을 하게 되면 이게 일자로 쭉 쓰여져있는 x같은 현상이 생겨

reakwon.tistory.com

 

systemd

systemd에서 끝 d는 daemon을 의미합니다. deamon은 background에서 실행이 되는  프로세스입니다. 그러한 deamon을 실행하고 관리하게 해주는 daemon이 바로 systemd입니다. systemd는 부팅하고나서 가장 먼저 실행되는 데몬입니다. 

이전에는 init이라는 데몬이 있었는데 이를 대체하고 init보다 기능이 추가되어서 나온 것이 systemd입니다. 그래서 이전의 init과 같이 PID가 1이 됩니다. 부모프로세스가 없으므로 PPID 또한 1이 됩니다. 

systemd는 리소스를 unit이라고 불리는 단위로 관리합니다. 어떤 type의 unit이 있을까요? 아래의 표로 정리하였습니다. 

.service .socket .device .mount .automount .swap .target .path .timer
.snapshot .slice .scope            

 

 - 여기서는 .service만 설명합니다. 가장 많이 쓰니까요~ .service에서는 service나 application을 서버상에서 어떻게 관리할지를 명세합니다. service의 시작, 중지, 그리고 어떠한 상황에서 자동적으로 실행하는지, 어떠한 종속성을 가지고 있는지에 대한 정보를 갖고 있습니다.

만약 .service를 추가하려면 /etc/systemd/system 디렉토리에 끝 확장자로 .유닛타입 식으로 써주면 됩니다. service의 경우에는 끝 확장자가 .service가 됩니다. 그리고 시스템은 일반적으로 unit file들을 /lib/systemd/system 하위에 복사하여 유지합니다. 여기서 아주 간단한 service를 등록하고 실행하는 방법을 알아보도록 하겠습니다. 

 

1. 실행 파일 생성

사용할 실행 파일(myservice.c)

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>

int main(){
        int fd;
        char buf[64] = "myservice start!\n";

        fd = open("/tmp/log.txt",O_CREAT|O_WRONLY|O_TRUNC,0644);
        //열기 실패시
        if(fd<0) return -1;

        write(fd, buf, strlen(buf));

        while(1){
                //계속 running되게 하기 위해 무한 loop
                sleep(1);
        }
        close(fd);
        return 0;

}

위 소스코드로 컴파일하여 아래의 실행 파일로 만들어보도록 하겠습니다. 권한 문제가 생길까봐 777을 부여했습니다.

# gcc myservice.c -o myservice
# chmod 777 myservice

 

2. Unit 파일 생성

우리는 service를 생성할 것이기 때문에 /etc/systemd/system 하위에 myservice.service 파일을 생성하도록 하겠습니다. 

[Unit]
Description=test service

[Service]
ExecStart=/home/ubuntu/systemd/myservice

[Install]
WantedBy=multi-user.target

 

2.1 Unit Section

보통 가장 처음 등작하는 Section입니다. 여기서는 유닛에 대한 meta data와 다른 유닛간의 관계를 설정하는 곳입니다. 

Description : 이 Unit에 대한 설명을 뜻합니다. 짧고, 간략하지만 핵심 정보를 담고 있도록 설명하는 곳입니다.

Documentation : 이 서비스에 대한 문서가 있는 URI를 제공합니다. man 페이지나 웹 사이트가 될 수 있습니다. 이런 정보들은 systemctl status 명령어에서 노출됩니다.

After : 이 Unit보다 먼저 실행되어야할 Unit들을 나열합니다.

Before : 이 Unit보다 늦게 실행되어야할 Unit들을 나열합니다. 

Requires : 이 Unit이 의존하는 모든 Unit을 나열합니다. 여기서 나열된 Unit들은 전부 성공적으로 실행이 되고 있어야합니다.

Wants : Requires와 유사합니다만, Requires보다는 그렇게 엄격하지 않습니다. 다른 Unit이 실패하더라도 지금 Unit을 실행합니다.

BindsTo : Requires와 유사합니다. 대신 연관된 유닛이 종료되면 같이 service가 종료됩니다.

 

2.2 Service Section 

Service Section은 서비스에만 적용할 수 있는 특징을 정의합니다. Unit에는 여러 종류가 있다고 위에서 표로 정의해놓았죠? mount도 있고, swap도 있고... 그중 Service에만 적용하는 구성입니다.

Type : service가 어떤 형태로 동작이 되는지를 설정합니다. systemd에게 이 service가 어떻게 관리되고 상태를 탐지하는지 알려주는 지시자입니다. 아래 중 하나로 동작이 됩니다. 

  ● simple : 명시하지 않을 경우 simple로 동작합니다. ExecStart는 설정이 되어 있어야합니다. 

  ● forking : service가 자식 프로세스를 생성할때 사용합니다. 이때 자식을 생성한 프로세스는 곧 장 나갈때 사용됩니다.

  ● oneshot : 프로세스가 오래 실행되지 않을때 systemd가 이 service가 종료되기를 기다려야할때 이 값을 사용할 수 있습  니다. service가 종료된 후 systemd가 진행을 계속하게 됩니다.

  ● dbus : 지정된 Bus Name이 D-Bus에 준비될때까지 기다리고, D-Bus가 준비되면 service가 실행됩니다.

  ● notify : service가 startup이 끝날때 notification(signal)을 발생시킵니다. 이런 상황이 발생할때 systemd는 다음 unit으로 넘어갑니다. 

  ● idle :  모든 작업이 실행될때까지 서비스가 실행이 되지 않습니다. 즉, 모든 작업이 실행되어서야 실행됩니다.

ExecStart : 실행할 command의 절대경로를 지정합니다.  

ExecStartPre : 서비스가 실행하기 전의 command를 지정합니다. 서비스 시작전 명령어를 실행합니다.

ExecStartPost : 서비스를 시작하고 나서의 command를 지정합니다. 서비서 시작 후에 명령어를 실행하기 됩니다.

ExecStop : 서비스가 stop될때 실행되어야할 command를 정합니다. 

Restart : systemd가 자동으로 재시작하려고 시도하는 상황을 정의합니다. alway, on-success, on-failure, on-abnormal, on-abort, on-watchdog를 사용할 수 있습니다. 

TimeoutSec : systemd가 service가 실행할때까지 기다리는 시간을 의미합니다. service를 stop할때까지 기다리는 시간이라고도 말할 수 있겠네요.

FailureAction : service 실패시 어떤 동작할 할지를 정의합니다. none, reboot, reboot-force, reboot-immediate, poweroff, poweroff-force, poweroff-immediate, exit, exit-force 중 하나를 사용합니다.

User : service가 실행될때 어떠한 권한으로 실행이 되는지를 설정합니다. user 이름이 될 수 있고, user id로 설정할 수도 있습니다. 그러나 user 이름이 알아보기 좋겠죠? 

Group : User와 마찬가지로 service가 실행될때 가지는 그룹 권한을 설정합니다. 

 

2.3 Install Section

보통 파일의 마지막에 존재합니다. 이 Section은 optional입니다. Unit이 enable하거나 disable 될때 Unit의 행동을 정의합니다.

WantedBy : 어떻게 Unit이 활성화(enable)되는지 명세합니다. 

Also : service가 enable, disable될때 집합 단위로 같이 enable, disable할 serivce들을 의미합니다.

Alias : 이 service의 별칭을 줍니다. 

 

3. service 실행, 상태, 종료

service 실행 : service를 실행하는 명령어는 아래와 같습니다. 서비스가 새로 추가됐으니, daemon을 다시 load하는 과정도 있어야합니다.

# systemctl daemon-reload
# systemctl start myservice

 

자, 실행이 되었다면 /tmp 하위에 log.txt라는 파일이 생겨나고 파일 내용이 적혀져 있어야합니다. 확인해볼까요? 

# cat /tmp/log.txt
myservice start!

 

위처럼 파일이 생겼으며 내용도 채워져있음을 확인했습니다. 그리고 현재 데몬이 실행되고 있는지 확인해봅시다. 

# ps -ef | grep myservice
root       42450       1  0 19:51 ?        00:00:00 /home/ubuntu/systemd/myservice

 

위와 같이 PID가 42450인 프로세스가 있는 것을 확인했습니다. 부모 PID는 1입니다. 시스템 데몬이라는 것을 알 수 있죠?

 

service 상태 확인 : service의 상태가 어떤지 보고 싶다면 status를 옵션으로 주면 됩니다. 4번째줄에 active로 실행중인 상태를 확인할 수 있습니다.

# systemctl status myservice
● myservice.service - test service
     Loaded: loaded (/etc/systemd/system/myservice.service; static; vendor preset: enabled)
     Active: active (running) since Mon 2022-06-27 19:45:00 KST; 51s ago
   Main PID: 42434 (myservice)
      Tasks: 1 (limit: 2295)
     Memory: 140.0K
     CGroup: /system.slice/myservice.service
             └─42434 /home/ubuntu/systemd/myservice

 6월 27 19:45:00 ubuntu-VirtualBox systemd[1]: Started test service.

 

service 종료 : service를 종료하고 싶다면 stop을 옵션으로 주면 됩니다.

# systemctl stop myservice
# systemctl status myservice
● myservice.service - test service
     Loaded: loaded (/etc/systemd/system/myservice.service; static; vendor preset: enabled)
     Active: inactive (dead)

 

service 재시작 : stop과 start를 하면 재시작이 되죠. 한번에 할 수도 있습니다.

# systemctl restart myservice

 

service 부팅시 시작, 해제 : 이 서비스를 부팅시에 자동으로 실행하게 만들 수 있습니다. 단, Install Section을 정의해놔야합니다. 반대로 부팅시 시작 해제하려면 disable을 사용하면 됩니다. 

# systemctl enable myservice
# systemctl disable myservice

 

기본적으로 systemd에 service를 등록하고 실행하는 방법을 알아보았습니다. 이 밖에도 훨씬 많은 내용이 존재하여 이 포스팅에 전부 담아낼 수가 없습니다. 그래서 아래의 페이지에서 필요할때 찾아서 적용하시면 되겠습니다.

https://www.digitalocean.com/community/tutorials/understanding-systemd-units-and-unit-files#install-section-directives

 

 

Understanding Systemd Units and Unit Files | DigitalOcean

 

www.digitalocean.com

 

https://www.freedesktop.org/software/systemd/man/systemd.directives.html

 

systemd.directives

Name systemd.directives — Index of configuration directives Unit directives Directives for configuring units, used in unit files....

www.freedesktop.org

 

반응형
블로그 이미지

REAKWON

와나진짜

,

tar

tar 명령어는 Tape Archiver의 약자로 여러 파일들을 하나의 파일로 묶어주는 명령어입니다. tar 명령어에 대해서 압축 명령어로 오해하시는 분들이 많은데, tar는 단순 파일을 하나로 묶는 명령입니다. 하지만 여러 옵션을 주어서 압축까지하는 것이 가능합니다. 예를 들어서 아래의 그림은 gzip이라는 압축 방식을 사용한 과정입니다. 아래의 그림을 보시면 쉽게 이해가 가능합니다.

file 1부터 file n까지가 있다면 tar 명령어를 통해서 하나의 files.tar 파일(확장자 .tar는 tar로 묶었음을 알리는 확장자입니다.)로 묶을 수 있습니다. 이때 압축한 상태가 되지는 않지요. 만일 압축방식의 하나인 gzip압축을 거치게 된다면 files.tar.gz(확장자 .gz은 gzip으로 압축이 되었다는 것을 알려주는 확장자입니다.)이라는 하나의 압축파일이 나올 수 있습니다. 그러니 ~.tar.gz은 tar로 파일들을 일단 하나의 파일로 묶고 나서 gzip 방식으로 압축을 한 파일이라는 것을 알 수 있겠죠.

그리고 압축을 해제할때는 이 과정의 역순을 거치게 됩니다. 

tar의 명령어 옵션은 너무 많아 포스팅에 전부 담을 수 없습니다. 주요한 옵션 몇가지만 보고 사용해도 문제없습니다. 

option 설명
-c(create) 파일 합치기
-v(verbose) tar의 과정을 보여주기, 굳이 사용하지 않아도 무방합니다.
-f(file) tar 아카이브 지정, 즉 압축 파일명을 지정합니다.
-x(extract) 파일 추출
-z(gzip) gzip 압축. 확장자 gz
-j(bzip2) bzip2 압축. 확장자 bz2
-t(list) 파일의 리스트 확인

 

위의 옵션들을 이용해서 tar로 파일들을 묶고 압축, 혹은 해제하는 방법을 아래의 명령을 통해서 보실 수 있습니다.

 

1. 파일 묶기

$ ls -l
합계 8
-rw-rw-r-- 1 ubuntu ubuntu 6  4월 24 12:33 file1.txt
-rw-rw-r-- 1 ubuntu ubuntu 6  4월 24 12:33 file2.txt
$ tar -cvf files.tar file1.txt file2.txt   <-- files.tar로 묶기
file1.txt
file2.txt
$ ls -l
합계 20
-rw-rw-r-- 1 ubuntu ubuntu     6  4월 24 12:33 file1.txt
-rw-rw-r-- 1 ubuntu ubuntu     6  4월 24 12:33 file2.txt
-rw-rw-r-- 1 ubuntu ubuntu 10240  4월 24 12:46 files.tar

 

 

2. 파일 풀기

$ ls -l
합계 12
-rw-rw-r-- 1 ubuntu ubuntu 10240  4월 24 12:46 files.tar
$ tar -xvf files.tar  <-- files.tar 파일 풀기
file1.txt
file2.txt
$ ls -l
합계 20
-rw-rw-r-- 1 ubuntu ubuntu     6  4월 24 12:33 file1.txt
-rw-rw-r-- 1 ubuntu ubuntu     6  4월 24 12:33 file2.txt
-rw-rw-r-- 1 ubuntu ubuntu 10240  4월 24 12:46 files.tar

 

3. gzip으로 압축

$ ls -l files/
합계 8
-rw-rw-r-- 1 ubuntu ubuntu 6  4월 24 12:33 file1.txt
-rw-rw-r-- 1 ubuntu ubuntu 6  4월 24 12:33 file2.txt
$ tar -cvzf files.tar.gz files <-- gzip 압축
files/
files/file1.txt
files/file2.txt
$ ls -l
합계 8
drwxrwxr-x 2 ubuntu ubuntu 4096  4월 24 12:55 files
-rw-rw-r-- 1 ubuntu ubuntu  185  4월 24 12:56 files.tar.gz

 

그런데 이렇게 명령어 옵션을 섞어서 쓸때 간과하는 점이 있는데 f는 아카이브 파일의 이름을 지정해야하는 옵션입니다. 그러니 -f 뒤에는 파일명이 나와야합니다. 이런 사실을 모르면 아래와 같은 에러 메시지를 볼 수 있게 됩니다.

$ tar -cvfz files.tar.gz files
tar: files.tar.gz: stat할 수 없습니다: 그런 파일이나 디렉터리가 없습니다
files/
files/file1.txt
files/file2.txt
tar: 앞서 발생한 오류로 실패 코드를 반환하며 빠져나감

 

만약 무슨 소리가 뭔지 모르겠다면 f를 항상 마지막에 써주고 파일명을 입력하시면 됩니다. tar -cvzf files.tar.gz files 이렇게요.

 

4. gzip 압축 해제

 

$ ls -l
합계 4
-rw-rw-r-- 1 ubuntu ubuntu 185  4월 24 12:56 files.tar.gz
$ tar -xvzf files.tar.gz <-- gzip 압축 해제
files/
files/file1.txt
files/file2.txt
$ ls -l
합계 8
drwxrwxr-x 2 ubuntu ubuntu 4096  4월 24 12:55 files
-rw-rw-r-- 1 ubuntu ubuntu  185  4월 24 12:56 files.tar.gz
$ ls -l files
합계 8
-rw-rw-r-- 1 ubuntu ubuntu 6  4월 24 12:33 file1.txt
-rw-rw-r-- 1 ubuntu ubuntu 6  4월 24 12:33 file2.txt

 

5. bzip2 압축

$ ls -l files
합계 8
-rw-rw-r-- 1 ubuntu ubuntu 6  4월 24 12:33 file1.txt
-rw-rw-r-- 1 ubuntu ubuntu 6  4월 24 12:33 file2.txt
$ tar -cvjf files.tar.bz2 files <-- bzip2 압축
files/
files/file1.txt
files/file2.txt
$ ls -l
합계 8
drwxrwxr-x 2 ubuntu ubuntu 4096  4월 24 12:55 files
-rw-rw-r-- 1 ubuntu ubuntu  191  4월 24 13:07 files.tar.bz2

 

6. bzip2 압축 해제

$ ls -l
합계 4
-rw-rw-r-- 1 ubuntu ubuntu 191  4월 24 13:07 files.tar.bz2
$ tar -xvjf files.tar.bz2
files/
files/file1.txt
files/file2.txt

 

7. 파일의 contents(list) 확인

$ ls
files.tar.bz2
$ tar -tf files.tar.bz2 <-- files.ar.bz2 안의 파일 확인, 압축 해제한것이 아님
files/
files/file1.txt
files/file2.txt
$ ls  
files.tar.bz2

 

여기까지만 알아도 tar을 통해서 압축하고 해제하는 데에는 아무 문제없습니다. 너무 쉽죠?

반응형
블로그 이미지

REAKWON

와나진짜

,