uju's Tech

Alpine Linux, Debian, CentOS Linux cp 차이를 통한 리눅스 삽질 과정 본문

Node

Alpine Linux, Debian, CentOS Linux cp 차이를 통한 리눅스 삽질 과정

ujusy 2022. 5. 18. 03:02

최근 회사 내에서 alpine linux와 debian 에서 cp가 다르게 동작하는 이슈가 있었는데 이유가 궁금해서 혼자 디깅해보았다. 

cp 이슈를 통해 여러가지 디깅해본 과정 및 관점을 기록 차원에서 남긴다.  ( 찾아봤던 시간이 아깝기도 해서 ㅎㅎ주륵..,,,

 

서론, 본론, 결론으로 이루어져있고 리눅스에 대해 조예가 깊지 않다는 점 감안하고 읽어주시면 좋을 듯 합니다.

잘못된 설명이 있다면 댓글 부탁드립니다.

서론

회사 내 프로젝트에서 Alpine Linux와 Debian 의 cp 명령어 동작 차이가 발생으로 인한 이슈가 있었다. 어떤 이슈인지는 인프랩 개발 블로그에 올라올 듯 하다. 

어떠한 차이가 있었는지 간단하게 설명해보겠다.

Alpine

  •  파일 a: 1 , b:2 , c: -> a
  • 파일 c에 a를 가리키는 심볼릭 링크를 생성한다. 
  • 아래 사진에서 심볼릭 링크가 생성되어있다.

 

그럼 여기서 cp b c 를 하면 어떻게 될까?

 

c -> a 심볼릭 링크를 끊고 b의 내용이 c 로 복사되는 것을 위와 같이 확인할 수 있다.

여기까지만 봤을 때는 음.. 잘 동작하는데? 라고 생각할 수 있다. 

Debian

  • debian linux도 마찬가지로 파일 a:1, b:2, c: -> a
  • 아래 사진에서 처럼 심볼릭 링크 형성 된 것 확인

debian linux는 여기서 cp b c 를 하면 어떻게 될까?

 

놀랍게도 아래 사진과 같이 심볼릭 링크를 끊지 않고 cp 가 된다.

debian

본론

본론 이라고하기에는...좀 그렇지만 여러 디깅 과정을 적어본다. 일단 debain이 저렇게 나오니 기업에서 많이 사용하는 cent OS는 어떻게 동작할까?

물론 같은 bash 이고 동일한 gnu/리눅스 os라 동일하다는 추측을 할 수 있지만 동일하게 시도해보았다.

CentOS

centos는 기본적으로 cp에 alias가 다음과 같이 되어있다. i 옵션은 overwrite 할 지 물어보는 옵션이다.

debian의 경우는 alias 되어있지 않아 따로 alias 설정 해줘야한다. 

 

centos

확인 결과 debian과 동일하게 동작한다.

 

centos

 

어떤 이유로 차이가 발생할까?

이제부터 생각의 흐름에 따라 디깅을 하게되는데 첫 번째로 찾아본 것은 쉘이다.

 

Q:쉘이 문제가 아닐까?

A: No

alpine linux의 경우 매우 가볍다는 장점을 가지고있으면서 가볍기 때문에 기본 패키지들이 설치되어있지 않다는 단점을 지닌다. 그래서인지(?) 기본 쉘을 확인해보면 Bourne Shell을 기본으로 갖고있는데 쉘을 확인하고 어..? cp는 명렁어니까(여기부터 잘못된 가정이었다. 뒤에서 설명하겠다.) 쉘에 포함되어있을텐데 bash 가 아니라서 서로 다르게 동작하나? 생각했었다.

 

alpine linux 기본 쉘

이런 생각을 가지고 debian, centos 기본 쉘인 bash로 변경하면 되지 않을까? 생각하고 아래와 같이 쉘을 변경해보았다.

 

alpine-linux

다음과 같은 명령어를 통해 변경가능하다.

apk update

apk add --no-cache bash

apk add --no-cahce shadow

chsh -s /bin/bash

bash 로 실행해주면 bash 로 변경된다.

docker 실행할 때 다음과 같이 쉘을 지정해서 실행해 줄 수도 있다. (docker exec -it 컨테이너 이름 /bin/bash)

 

이렇게 변경 후에 다시 시도해보았는데 다음과 같이 기존 sh 일 때와 동일하게 동작한다.

 

alpine-linux

 

 

사용하는 cp가 bash에 속한 명령어가 아니네..?

동일한 shell 로 변경했음에도 다르게 동작하는 것은 cp가 shell에 종속적인 명렁어가 아니라는 의미가 되는 것 같다. alpine linux의 /bin 에 들어가보면 다음과 같이 나온다. 

 

alpine-linux /bin

어..? 보는 순간 shell이 문제가 아닌데..?

cp --help를 쳐보자. 다음과 같이 나온다.

 

alpine-linux cp --help

alpine linux는 다른 linux와는 달리 gnu가 아닌 busybox로 구성되어있다.

 

아래는 위키백과 내용이다. (참고)

 

일단 구성하는 소프트웨어에서 alpine linux는 musl libc, busybox로 구성되어있고 debian, centos는 glibc, gnu로 구성되어있다. 

구성 소프트웨어가 다르니 충분히 다르게 동작할 수 있다는 것을 인지할 수 있었다. 그러면 설정에서 변경할 수 있는 것은 없어보인다.

 

근데 일반적으로 생각해보면 alpine linux에서 동작하는 것 처럼 cp b c 를 할 때 b의 값이 c에 복사되기를 원하지 c와 링크되어있는 a가 변경되기를 원하지는 않을 것이다. 그리고 cp b c 를 했는데 a 가 변경된다면 의도한 작업이 아니고 a의 원본 데이터가 덮어 씌워지기 때문에 중요 데이터일 경우 큰일날 수 있다.

 

그럼 gnu/linux os로 구성된 리눅스(debian, centos) 에서 cp [source] [dest] 를 할 때 dest가 심볼릭링크가 연결된 파일일 경우 링크를 끊고 복사할 수 있어야한다. 링크를 끊고 dest만 덮어씌우고싶은 경우에는 다음과 같은 옵션을 주어 해결할 수 있다.

다음 사진들은 cent os 환경이다.

 

cp --remove-destination [source] [destination]

 

centos

c의 inode를 확인해보면 c에 연결되어있던 심볼릭 링크가 끊긴 것을 확인할 수 있다.

centos

 

결론

🤔

먼가 해결했다기에는 찝찝해서 삽질이라고 적었다. 개인적으로 몇 가지 생각해본 의견은 다음과 같다.

 

1️⃣   docker image로 사용할 경우에는 기업에서 많이 사용하는 cent os 로 바꾸자. 이유는 비교적 자료가 많다.   

        *️⃣   alpine은 가볍고 작아서 aws docker image 비용도 얼마 나가지 않는 등의 장점이 있으니 토이프로젝트 할 때..쓰는것도..? 

 

2️⃣  alpine을 무조건 써야하는데 명령어 몇 가지는 타 리눅스와 동일했으면 좋겠다?

        *️⃣  명렁어 파일 복사 붙여넣기 해오기. -> 이건 좀 아닌듯 싶은데,, 잘 될지도 모르겠다.

 

3️⃣   debian, centos, ubuntu 등.. 에서 cp를 쓰는데 위의 경우처럼 가리키는 파일가지 overwrite 되는 것을 막고싶으면 cp --remove-destination [source] [destination] 옵션 을 써주자. cp 에 많은 옵션이 있으니 잘 활용하자.

 

 

삽질할 때 alpine이 문제라고 생각하면서 삽질한 탓에 꽤 시간을 소요했다. 

딱히 둘 다 문제라고 할 만한 것은 없고 이러한 차이가 있을 수 있으며 차이가 발생하는 이유는 구성 소프트웨어의 차이다..? 라고 정리할 수 있을 것같다.

 

일단 왜 다르게 동작하는지 너무 궁금해서 삽질을 시작해보았는데 한 2시간~3시간 삽질해서(docker 실행해보기 포함..ㅜ 환경 구성하는게 오래걸렸다)  시간이 아깝다는 생각도 살~짝 들었다. 

그래도 학교다닐 때 이후로 리눅스 슬쩍 만져봐서 재미있었다.  그러면서 호기심도 나름 해소되었고..!

근데 쓰고나니 별거 없어서 살짝 슬퍼진다. 또 alpine linux 로 배포하면서 문제가 있었는데 이것도 잘 다듬어서 정리해볼까 싶다

 

참고

 

https://busybox.net/

https://www.gnu.org/software/coreutils/manual/html_node/cp-invocation.html

 

cp invocation (GNU Coreutils 9.1)

If copying recursively, copy the contents of any special files (e.g., FIFOs and device files) as if they were regular files. This means trying to read the data in each source file and writing it to the destination. It is usually a mistake to use this optio

www.gnu.org

 

Comments