Docker 설치 사용 후기

최근에 홈오토메이션을 잠깐 만져보다가 Docker를 접하게 되었다.

그동안 도커도커 얘기만 들어보고 개념만 들어봤지 이게 무엇인지 제대로 몰랐는데 이제는 좀 써봐야겠다 싶어서 도커에 대한 책도 한권 구매해서 정독하고 마이크로서버도 도커 기반으로 변경. 어차피 몇가지 서비스가 운영되지 않았기 때문에 도커로 옮기는건 별로 어렵지 않았으나 이왕이면 깨끗한 상태에서 돌리는게 기분 좋으니 CentOS 7 로 재설치하고 도커 기반으로 이전했다.

plex, transmission, nginx, homebridge 정도만 도커로 돌려보니 이제 이게 뭔지 좀 알 것 같다.

도커를 사용해본 후기.

  1. 전가상화와 비교할 수 없을 정도로 강력함.
    ESXI를 이용해 가상화로 서버를 돌려봤는데… 이건 운영체제 선택의 자유로움이 있고 정말 완벽한 격리환경이 되는 반면에, 가상화를 한다해도 자원을 너무나 많이 소모했다. 특히 게스트 운영체제 구동에 자원이 많이 드니… 이렇게까지 해야하나 싶었는데, 도커는 호스트 운영체제의 성능을 거의 그대로 쓸 수 있고, 자원도 많이 들지 않는다.아마 리눅스 서버를 가상화해서 쓴다면 ESXI보다 Docker가 정답인듯하다.
  2. 라이브러리 설치에서 해방
    yum이 나오면서 의존성에 대한 패키지 설치는 거의 자동화가 이루어졌긴하지만 서버에 프로그램을 설치하다보면 수많은 패키지들이 같이 설치가 된다. 시스템이 얼마나 더럽혀지는지도 알 수가 없고, 내가 쓰던 프로그램을 언인스톨한다고 해서 이 라이브러리와 패키지들이 같이 삭제되는건 아니기 때문에 과도한 관련 패키지와 라이브러리 설치는 별로 마음에 들지 않았었다.그런데, 도커로 오니 이러한게 한방에 해결. 더이상 운영체제가 각종 라이브러리 파일로 더럽혀질 일은 없을듯하다.
  3. 컨테이너 실행 옵션이 바뀌면 컨테이너를 통째로 지우고 다시 만들어야함.
    도커 사용시 약간 귀찮은 점. 어쩌면 방법이 있는데 내가 도커를 아직 잘 몰라서 못 찾은 것일 수도.
  4. 이미지에서 지원하지 않는 기능과 옵션에 대해서 내가 처리 불가능.
    사용하고자하는 이미지마다 정해진 옵션이 있고 이 옵션들에 대해서만 사용 가능하다.
    물론 그 부분을 내가 수정하여 이미지를 만들면서 사용하면 해결가능하다.
  5. 하지만 그럼에도 장점이 크다.
    호스트 운영체제의 시스템을 전혀 건드리지 않으면서 프로그램을 실행할 수 있다는건 정말 큰 장점.
  6. 실서비스에서 사용 가능한가…?
    사용해본 경험으로는 실서비스에 충분히 사용가능할듯하다.
    특히, 같은 이미지만 사용한다면 어디서나 같은 컨테이너를 돌릴 수 있다는게 최고의 장점인 것 같다.
    경험상 리눅스서버 사용시에는 운영체제 버전이 다르면 라이브러리 충돌 때문에 애먹는 경우가 많은데 도커가 그 해답이 될 수 있을 것 같다.

도커도커 왜들 그리 도커를 찾았나 얘기해서 사용해봤더니 실제로 아주 훌륭했다. 좀더 사용해보면 장단점이 더 많이 보이겠지.

CentOS 7에 plexpy 설치

plex 서버를 잘 사용 중인데 plexpy라는게 있다고 한다. 대강 보니 모니터툴 같은데 일단 리눅스에서 plexpy 를 설치해본다. 인터넷에 있는 몇몇 문서들은 도커를 이용한 설치를 예시로 하고 있는데 내 서버들은 아직 도커를 쓰지 않으므로 그냥 설치하는 것으로.

리눅스는 CentOS 7. plexpy 홈페이지에 들어가 InstallGuide 문서를 읽어본다.

https://github.com/JonnyWong16/plexpy/wiki/Installation

GIT을 이용하여 소스 코드를 다운 받는다.

git clone https://github.com/JonnyWong16/plexpy.git

[root@localhost source]# git clone https://github.com/JonnyWong16/plexpy.git
 Cloning into 'plexpy'...
 remote: Counting objects: 15652, done.
 remote: Total 15652 (delta 0), reused 0 (delta 0), pack-reused 15652
 Receiving objects: 100% (15652/15652), 77.18 MiB | 2.67 MiB/s, done.
 Resolving deltas: 100% (8905/8905), done.
 [root@localhost source]#

설치문서에는 /opt 에 설치하는 것을 예로 들고 있지만 이 경로를 난 좋아하지 않으므로 /usr/local/plexpy 에 설치할 예정.

다운 받은 내용을 /usr/local/plexpy 로 이동한다.

[root@localhost source]# mv plexpy /usr/local/
 [root@localhost source]# cd /usr/local/plexpy
 [root@localhost plexpy]#

plexpy.py를 실행하면 StandAlone 으로 실행하는 것 같지만 난 데몬서비스가 더 좋으므로 관련 문서를 읽어본다.

https://github.com/JonnyWong16/plexpy/wiki/Install-as-a-daemon

리눅스인 경우 다음의 문서를 읽어보라고 한다.

https://github.com/JonnyWong16/plexpy/blob/master/init-scripts/init.systemd

보여지는 스크립트 파일 내용을 vi 를 이용해 plexpy.service 파일로 입력한다.

파일 안에 있는 /opt 로 시작하는 경로들을 나에게 맞도록 /usr/local q로 시작하도록 수정한 다음 저장한다. 실행 유저과 그룹도 plexpy 로 변경.

.service 파일은 보통 /lib/systemd/system 에 저장한다고 하니 그곳으로 옮겨주고 스크립트를 재로딩한 다음, 제대로 읽혀지는지 테스트해본다.

[root@localhost plexpy]# mv plexpy.service /lib/systemd/system
 [root@localhost plexpy]# systemctl daemon-reload
 [root@localhost plexpy]# systemctl status plexpy.service
 ● plexpy.service - PlexPy - Stats for Plex Media Server usage
 Loaded: loaded (/usr/lib/systemd/system/plexpy.service; disabled; vendor preset: disabled)
 Active: inactive (dead)
 [root@localhost plexpy]#

서비스를 시작한다.

[root@localhost plexpy]# systemctl start plexpy.service
 Job for plexpy.service failed because the control process exited with error code. See "systemctl status plexpy.service" and "journalctl -xe" for details.
 [root@localhost plexpy]#

 

에러가 난다. 에러메시지대로 status 명령을 입력해본다.

[root@localhost plexpy]# systemctl status plexpy.service
 ● plexpy.service - PlexPy - Stats for Plex Media Server usage
 Loaded: loaded (/usr/lib/systemd/system/plexpy.service; disabled; vendor preset: disabled)
 Active: failed (Result: exit-code) since 화 2017-09-12 14:24:11 KST; 1min 10s ago
 Process: 23144 ExecStart=/usr/local/plexpy/PlexPy.py --quiet --daemon --nolaunch --config /usr/local/plexpy/config.ini --datadir /usr/local/plexpy (code=exited, status=217/USER)

9월 12 14:24:11 localhost.localdomain systemd[1]: Starting PlexPy - Stats for Plex Media Server usage...
 9월 12 14:24:11 localhost.localdomain systemd[1]: plexpy.service: control process exited, code=exited status=217
 9월 12 14:24:11 localhost.localdomain systemd[1]: Failed to start PlexPy - Stats for Plex Media Server usage.
 9월 12 14:24:11 localhost.localdomain systemd[1]: Unit plexpy.service entered failed state.
 9월 12 14:24:11 localhost.localdomain systemd[1]: plexpy.service failed.
 [root@localhost plexpy]#

 

설치 문서를 읽어보니 환경설정에 대한 내용을 하나도 실행 안한 것이었다.

유저를 추가하고 권한을 준다.

[root@localhost plexpy]# adduser --system --no-create-home plexpy
 [root@localhost plexpy]# chown plexpy:plexpy -R /usr/local/plexpy
 [root@localhost plexpy]#

 

이제 다시 시작해보면 에러가 나지 않는다.

[root@localhost plexpy]# systemctl start plexpy.service
 [root@localhost plexpy]#

 

서비스를 자동실행으로 등록한다.

[root@localhost plexpy]# systemctl enable plexpy.service
 Created symlink from /etc/systemd/system/multi-user.target.wants/plexpy.service to /usr/lib/systemd/system/plexpy.service.
 [root@localhost plexpy]#

 

웹브라우저로 서버의 8181 포트를 열어보면 다음과 같은 화면이 나온다. 이제부터는 웹에서 설정!

그런데 막상 설치해서 보니까 이게 뭐… 딱히 모니터링이라 하기도 애매하고… 어디다 써야할지는 잘 모르겠다. 아파치에 같이 물릴려고 했는데 귀찮아서 그냥 쓰는 것으로.

HP MicroServer Gen8

독일의 컴퓨터유니버스(http://www.computeruniverse.net)에서 직구한 마이크로서버 Gen8이 도착했다.

우리나라 가격으로는 35만원 정도인데 컴퓨터유니버스를 이용하면 배송비 모두 포함 27만원 정도가 든다. 단 거의 3주에 가까운 시간을 기다려야 했으니…. 직구를 처음해보는 나로써는 무진장 답답했다. 컴퓨터유니버스에서 독일우체국까지는 금방간다. 그런데 거기서 한국으로 오기까지 거의 열흘가까이가 걸렸다. 한국에 온 다음에는 2일인가 3일만에 도착.

여튼 무사히 도착했으니 박스 뜯으며 개봉.

img_1155

박스 크기가 거의 라면 박스 크기.

img_1156

내부에는 종이를 구겨서 완충재로 넣어놨다. 그덕분에 다행히 박스는 아주 깨끗한 모습으로 도착.

img_1157

상자를 열고 컴퓨터를 꺼낸다. 전원케이블 2개가 들어있다. 생각보다 컴퓨터가 무겁다.

img_1160

기본사양은 하드디스크가 들어있지 않기 때문에 따로 준비한다. 운영체제용으로는 얼마전 RMA 받은 히타치 500기가 하드디스크, 데이터 저장용으로 웨스턴디지털 4TB 하드디스크, 토렌트 돌릴 용도로 무상분양 받은 삼성 250GB 하드디스크를 캐디에 조립한다.

img_1158

서버 뒤의 핸드스크류를 돌린 다음 뚜껑을 뒤로 밀어서 연다. 옆쪽에 메모리 슬롯이 보이고 2GB ECC 메모리가 꽂혀있다. 미리 준비한 삼성 PC12800 ECC 8GB 메모리 2개를 꽂아서 16기가 메모리를 장착했다.

img_1161

작업방에 두고 세팅 중… 아내가 아주 오래전에 쓰던 모니터와 키보드도 연결했다. iodd를 연결해서  CentOS 설치. (이럴 때 느끼지만 정말 iodd는 잘 산 것 같다.) 운영체제는 CentOS 7을 설치했다. 6버전대가 익숙하긴한데 공부도 할겸 개인용도니까 7 버전으로 처음 설치.

처음 시동하면 지혼자 몇번 꺼졌다켜졌다 계속 반복한다. 일종의 초기화 과정으로 생각하고 가만히 내버려두면 된다.

내가 제일 중요하게 생각했던 소음 문제.

사용해보니 부팅시에는 굉장히 소음이 큰데 부팅이 완료되면 소음이 적다. 일반적인 사무실에서 조용할 때 나는 컴퓨터 소리 정도? 그냥 사무실이라고 생각하면 쓸 수 있을 것 같다. 하지만 집안에서라면 좀 어려울 것 같다. 집안에 아무런 전자기기나 TV도 작동하지 않는 조용할 때에는 소음이 들린다.

가상화를 위한 준비 #2 – 네트워크

가상화를 위한 준비에서 네트워크 준비에 대해 고민을 많이 했다.

인터넷에서 찾아본 대부분의 문서들이 가정에서 공유기 밑에 ESXi를 설치하는 문서만 있었기에 거의 도움이 되지 않았다. 공유기 밑에서 DHCP 환경으로 ESXi를 설치하는 것은 별로 어려운 일이 아닐뿐더러, IP가 계속 할당되기 때문에 IP에 대해서도 고민할 필요가 거의 없다.

난 IDC에 서버를 넣어야하고 고정IP가 제한적으로 부여되기 때문에 어려움이 많았다.

[gads_468x60]

여기서 중요한 것은 ESXi를 관리하는데에 쓰이는 IP와 실제 서버에 사용될 IP, 즉 최소 2개 이상의 IP가 확보되어야만 ESXi를 사용할 수가 있다. 이 사실을 아주 오랜 시간과 실패 끝에 알아냈다. 인터넷에 있던 문서들은 공유기 밑에서 사용했으므로 이러한 문제를 하나도 겪지 않았을 것이다. IP 하나로는 ESXi를 운영할 수가 없는데 그 이유는 다음과 같다.

  1. ESXi 서버는 자체적으로 80, 443, 22번 등의 중요한 포트를 관리용 포트로 사용한다.
  2. 그 포트 번호를 다른 포트 번호로 바꿀 수 없다면 이 포트를 해당 IP의 서비스 포트로 사용할 수가 없다는 얘기가 된다.
  3. VMWare의 kb에는 이 포트번호들을 바꾸는 방법이 설명되어 있으나 실제로는 적용 되지 않는다.

결론적으로 3번을 시도하느라 엄청난 시도와 실패를 경험하고 VMWare에서 만든 문서가 잘못되어 있다는 결론이 났다. 아이피가 2개이면 이 모든 문제를 고민할 필요가 없어지게 된다.

그래서 IDC와 계약시 부여받은 IP는 3개였다. 하나는 ESXi의 관리용으로, 하나는 서비스용으로, 하나는 예비용으로 사용하고 있다. ESXi를 설치할 때 관리용 IP로 입력을 하고, ESXi 위에서 NAT와 방화벽을 담당할 서버에 서비스용 IP를 부여했다.

부디 ESXi를 실제 서비스에 응용하는 사람들은 나 같은 실패를 겪지 않기를.

가상화를 위한 준비 #1 – 서버 하드웨어

가상화를 위한 서버 하드웨어와 네트워크를 준비할 때의 참고사항을 정리해본다.

[gads_468x60]

일단 서버 하드웨어를 준비해야했다.

보유하고 있는 서버는 HP DL120G7 기본형 모델이었다. Intel Xeon E3-1220 프로세서와 4GB ECC 메모리, 250GB 하드디스크를 장착한 1U 사이즈 서버이다.

ESXi를 설치해서 게스트 운영체제들을 운영할 때 중요한 것은 CPU보다는 메모리와 디스크이다.

메모리

c03186237

메모리는 게스트 운영체제마다 개별적으로 쓰는 부분이라 내가 설치할 게스트 운영체제들이 모두 쓸 메모리의 크기에 예비용 메모리량과 시스템이 사용하는 메모리량을 고려해야한다. ESXi도 일종의 운영체제이므로 메모리를 사용하게 된다. ESXi를 실제 운영시에는 2.5GB 정도 사용하고 있으나 약 4GB 정도는 ESXi가 쓴다고 예측하면 좋을 것 같다. 참고로 ESXi는 4GB 미만의 메모리에서는 설치 자체가 되지 않는다. 4GB의 메모리를 가지고 있다 하더래도 비디오메모리 등으로 공유메모리가 나가게 되어 실제 가용메모리가 4GB가 되지 않으면 설치가 되지 않는다. 결국 메모리는 8GB ECC 메모리를 4개 장착해서 32GB로 설치했다.

하드디스크

western-digital-blue-wd10ezex-hard-drive

디스크는 사실 요새 가격이 너무 떨어졌기 때문에 용량을 증설하는데에는 어려움이 없으나 가상화를 하게되면 디스크 속도가 저하되므로 이에 대해 고민해봐야한다. 많은 커뮤니티 사이트들과 카페를 돌아다녔을 때, SSD로 하면 쾌적한 성능이 나온다고 되어있으나 여유롭게 운영체제를 이것저것 설치해보기에는 SSD는 비용이 너무 많이 든다는 문제가 있었다. 결론적으로 하드디스크는 기존에 설치되어있던 하드디스크를 모두 제거하고 Western Digital의 7200RPM 1TB 하드디스크를 두개 구입하여 넣었다. 차후에도 디스크를 더 추가할 계획을 가지고 있다.

실제 운영 상황에서 CPU는 아직까지 크게 모자라지 않았으나 예측대로 메모리는 많이 소모되었다. 디스크는 스왑메모리 때문에 그런지 생각보다 공간이 많이 소모되었다. 디스크를 처음부터 크게 장착하는 것이 좋을 것 같다.

이정도 하드웨어를 준비해서 실제 운영을 시작했는데 사실 자원은 굉장히 여유로웠다. 대부분의 경우에 CPU는 모든 서버들의 사용량 총합이 500MHz가 채 되지 않았다. 이걸 본다면 막강한 CPU를 장착하고도 효율적으로 쓰지 못하는 서버들이 얼마나 많은지 알만하다.

드디어 서버에 하드디스크 추가

그동안 1년간 열심히 일해준 서버에 하드디스크를 추가해줬다.

하드디스크가 남기도하고 해서 어디다 쓸까 고민하다가 서버에 추가해주기로 결정. 그동안은 원격백업을 해왔는데 이젠 로컬백업을 할 수 있을 것 같다.

새로 추가할 웨스턴디지털의 500기가 하드디스크. 그린 모델인데 속도가 5400RPM으로 좀 느리다. 어차피 백업용도로 장착될 것이기 때문에 속도는 별로 상관이 없을듯하다.

내 서버는 HP DL120 G7 모델인데 하드디스크를 추가하려면 가이드가 필요했다. HP 정품 하드디스크 가이드는 따로 판매하지 않기 때문에 옥션에서 주문. 약 35000원 정도가 들었다. 정품인지 중국산인지는 모르겠으나 어쨌튼 장착해보니 잘 되었다.

토요일에 늦잠을 좀 자고 가산에 있는 LG IDC에 도착. 직원분과 함께 주민등록증을 맡기고 신분증을 받은 다음 서버가 있는 4층으로 향했다. 중간중간 출입증으로 보안장치를 세번 정도 통과해야했다. 물론 곳곳에 CCTV도 있다. 서버가 있는 곳은 신발을 벗고 실내화로 갈아신고 들어가야한다. 문을 열자마자 소음이 느껴졌다. 으…

케이지를 열고 들어가서 내 서버를 찾았다.

이게 내 서버. 사진에서는 가장 중간에 있다. 랙에서는 비교적 밑에 쪽에 위치했다. 아래 위로는 비슷한 대역대의 서버들이 모여있었고 대부분은 1U 크기의 서버들이었다.

일단 콘솔모니터와 키보드를 연결한 다음,서버에 셧다운 명령을 내리고 전원이 내려간 것을 확인했다. 그리고 서버의 블랭크 가이드를 빼고 그자리에 가져온 하드디스크를 밀어넣었다. 뭐 볼트 너트도 필요 없이 그냥 손으로 빼고 그냥 밀어넣으면 끝.

다시 전원을 올리고(전원 버튼을 못찾아서 해맸다. 전원불이 들어오는 램프가 버튼이었다. 이런…;;) 다시 루트로 로그인.

파티션 작업을 하려고하니 GPT 파티션 타입이라는 경고가 나왔다 아마 맥에서 외장하드로 쓰던 것이라 그런가보다. 파티션을 삭제하고 다시 파티션을 잡은 다음 포맷. 파티션은 하나로 잡았다. 사용가능한 용량은 총 460기가 정도. 포맷을 마치고 임시로 마운트하기 위해 백업디렉토리를 생성하고 마운트를 한번 해봤다. 그리고 테스트로 파일을 하나 카피해보니 잘된다.

부팅시 추가하기 위해 /etc/fstab에 하드디스크 UUID를 적고 마운트 디렉토리를 설정. 테스트하기 위해 한번 재부팅해본다. 마운트가 자동으로 잘되었으니 로그아웃한다.

콘솔모니터와 키보드를 다시 잘 정리하고 직원분께 간단하게 인사를 하고 나왔다.

백업용 쉘스크립트를 다시 작성해야하는데 언제 다 할래나…

Cacti에서 CPU Usage 표시하기

모니터링툴인 Cacti를 설치하면 기본으로 있는 그래픽 템플릿으로 여러가지 모니터링 템플릿이 들어있는데 아쉽게도 여기에는 CPU 사용률에 대한 그래픽 템플릿이 없다. 물론 Host MIB – CPU Utilization이나 ucd/net – Load Average 같은 템플릿이 있지만 이것은 내가 원하는 ##%형태의 숫자를 보여주는 것이 아니었다.

그래서 역시 오늘도 구글님에게 물어본 결과 괜찮은 답변을 받았다. 역시나 이미 나와 같은 고민을 했던 외국인들이 있었다.

http://forums.cacti.net/about15412.html

글을 읽어보면 2-way system / 4-way system / 8-way system 으로 파일이 나뉘어있다. 서버의 CPU에 맞도록 다운로드 받는다. 리눅스 시스템의 경우에는 /proc/cpuinfo 파일에 프로세서 정보가 나와있으니 여기에 CPU가 몇개나 보이는지 확인한 후 적당한 것을 다운로드 받으면 된다.

내 서버의 경우에는 Intel Xeon E3-1220 프로세서를 사용하고 있고 1개의 CPU에 4개의 코어가 장착되어있으므로 4-way용으로 다운 받았다.

다운로드 받은 후 Cacti의 메뉴 중 import templete에 들어가서 다운로드 받은 xml 파일을 선택하면 cacti에 CPU 사용률을 표시할 수 있는 그래픽 템플릿이 생성된다.

JSP를 응용하여 계정용량 파악해보기

내 서버에서는 무료로 웹호스팅 서비스를 운영 중인데 사용자지원페이지를 만들어보았다.

사용자지원페이지에는 현재 계정용량 파악하기라는 메뉴를 넣기로 했는데 정작 사용자 계정용량 파악하는 방법을 찾을 수 없었다는 것.

그래서 예전에 PHP로 만들었던 기억과 구글에서 찾은 몇가지 정보를 더하여 계정용량 검색기능을 만들어보았다.

일단 리눅스서버에서 쓰는 계정용량 검색 명령어는 ‘du -shm /home/계정ID’의 형태이다. 이 시스템명령어를 수행하여 결과값을 가져오면 된다는게 기본 원리.

<%@page import="java.io.InputStreamReader"%>
<%@page import="java.io.BufferedReader"%>
<%
String command = "du -shm /home/" + id;

//계정 총용량 구하기
String info_space = "";
Process p = null;
BufferedReader br = null;

try {
    p = Runtime.getRuntime().exec(command);
    br = new BufferedReader(new InputStreamReader(p.getInputStream()));
    String line = null;
    while ((line = br.readLine()) != null) {
        line = line.split("/")[0].trim();
        info_space = "약 " + line + " MByte";
    }
} catch (Exception e) {
    info_space = "계정 총용량을 확인할 수 없습니다.";
}
%>

자바에서는 시스템명령을 수행할 때 Runtime 클래스를 사용하면 된다. 이 클래스를 사용해서 돌아온 결과값을 while을 이용하여 읽어들이면(여기에서 BufferedReader와 InputStreamReader 클래스가 필요하다.) 명령을 수행한 결과를 알 수 있다.

내가 뽑고 싶은건 계정사용 공간이었는데 리눅스의 du -shm 명령어는 잡다한 글귀가 붙어있기 때문에 이것을 split와 trim 함수를 이용해서 필요한 부분만 잘라주었다. 이 부분은 아마 정규표현식이나 아니면 다른 어떠한 방법으로 더 간단히 할 수 있을 것 같지만 일단 내가 아는 명령어는 이정도이므로. du 명령어의 옵션으로 준 -h는 사람이 읽기 쉬운 형태로 보여준다. 예를 들면, 기가바이트 단위의 데이터는 G로 메가바이트는 M로 표시해준다. 일관성이 없어지기 때문에 웹페이지에서도 이것을 표시할 때 일관성이 없어지게 되므로 추가해서 -m 옵션을 주어서 무조건 Mega Byte 단위로 처리하게 만들었다.

이 방법을 이용하면 생각보다 쉽게 계정용량을 MByte 단위로 환산하여 출력할 수 있게 된다.

한가지 주의할 점은 생각보다 계정용량이 정확하게는 표시되지 않는다. 또한 자바의 Runtime 클래스는 어찌된 영문인지 접근권한에 상관 없이 실행될 수 있는 것 같다. 악의적인 사용자가 rm 등의 명령어를 사용할 시 크게 문제가 될 수 있을 수 있으니 실행할 명령어를 파라미터로 받아서 수행한다거나 하는 경우는 절대 없어야 할 것 같다.