'Linux'에 해당하는 글 18건

간만에 재미진 일.


간만에 사이트 운영팀에서 오류 문의가 속출했다. 등록이 안된다느니, 상세 페이지가 빈화면으로 나온다느니... 훗~ 걱정마라. 언제나 처럼 이 오빠가 해결해 줄테니.


우선 이 님들의 증상이 나에게도 동일한지 확인하였다. 특정 페이지들이 서버 500 에러도 있었지만 status 200 인데 빈화면이 나오는 기괴한 장면이 보여졌다. 동일한 소스의 개발 서버에는 정상적으로 작동하고 있었다. 실서버 로그를 확인해보니, 어제 아무개팀에서 인증서를 갱신했다.(내가 하던걸 왠일로...) 근데 로그를 뒤져보니 그 시간 이후로 오류가 속출했다. 잡았다, 요놈!! 공통적으로 주로 나온 오류들이다. 


INFO [main] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler ["https-jsse-nio-8443"]

java.util.logging.ErrorManager: 4

java.io.FileNotFoundException: /usr/share/tomcat8/logs/catalina.2020-01-08.log (Permission denied)

        at java.io.FileOutputStream.open0(Native Method)

...


INFO [main] org.apache.catalina.core.StandardService.stopInternal Stopping service [Catalina]

[localhost-startStop-2] ERROR o.a.c.s.StandardManager - Exception unloading sessions to persistent storage

java.io.FileNotFoundException: /usr/share/tomcat8/work/Catalina/localhost/ROOT/SESSIONS.ser (Permission denied)

        at java.io.FileOutputStream.open0(Native Method)

...


SEVERE [https-jsse-nio-8443-exec-6] org.apache.catalina.core.StandardWrapperValve.invoke Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception

 org.springframework.web.multipart.MultipartException: Could not parse multipart servlet request; nested exception is java.io.IOException: org.apache.tomcat.util.http.fileupload.FileUploadBase$IOFileUploadException: Processing of multipart/form-data request failed. /var/cache/tomcat8/work/Catalina/localhost/ROOT/upload_46c524e4_8548_4273_9717_ff2e98ca4a2d_00000000.tmp (Permission denied)

        at org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.parseRequest (StandardMultipartHttpServletRequest.java:112)

...


그리고 status 200 이지만 빈화면 나오면서 발생한 로그...


[https-jsse-nio-8443-exec-9] ERROR o.s.b.w.s.ErrorPageFilter - Cannot forward to error page for request [/manage/admin/9] as the response has already been committed. As a result, the response may have the wrong status code. If your application is running on WebSphere Application Server you may be able to resolve this problem by setting com.ibm.ws.webcontainer.invokeFlushAfterService to false


조금 당황스러웠다. 평소에 보던 오류도 아니고... 한가지 힌트는 Permission denied 하난데. 히스토리를 보니 인증서 갱신하고 몇번 톰캣 재부팅을 하는 과정에서 사용자 권한이 좀 꼬인것 같았다. 문제되는 파일들의 소유자가 모두 ROOT 로 실행되어 있던것이 문제. 후... 인증서 갱신하고 톰캣 재부팅만 하면 되는건데 뭐 때문에 ROOT 로 톰캣을 실행시켰을까 ㅡ.ㅡ 톰캣 재부팅으로도 문제는 해결되지 않았다. 이 파일들을 다 일일히 어떻게 찾아서 지우나 고민하던 중 빛과 같은 한 줄기 로그.


[localhost-startStop-1] ERROR o.a.j.EmbeddedServletOptions - The scratchDir you specified: [/usr/share/tomcat8/work/Catalina/localhost/ROOT] is unusable.



캐쉬 디렉토리 같은데 /usr/share/tomcat8/work/Catalina/localhost/ROOT 이 디렉토리를 삭제하니 문제가 해결됐다.

오예~


WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,

웃픈 tomcat 서버

Daily/Prog 2019. 8. 6. 20:55



오늘의 웃픈 에피소드.


회사에는 구성원이 있고 그들의 역할도 있고 그에 따른 책임도 있고 단계도 절차도 있다. 그것은 때로는 많은 사람들을 피곤하게 하고 더 많은 시간이 소요되는 비효율적일 때도 있다. 나에게도 이런 상황이 닥쳤지만 이 상황을 효율적으로 바꾸려면 그들이 똑똑해지거나 그들의 역할을 누군가가 도와주는 방법이 있다. 하지만 그들이 하루 아침에 똑똑해질 수는 없고 그들의 역할에 내가 침범하면 불쾌해 할 것이다. 그래서 난 그냥 비효율적으로 있기로 했다.


개발서버가 필요했다. 필요한건 tomcat 밖에 없었다. 어딘가에게 요청했다. 이 어딘가는 앞으로 열심히 서버를 만들, 서버 전문가가 되려고 준비하는 집단이다. 곧 ip 와 pem 키가 전달됐다.


putty 접속을 했는데 user 가 centos. 갑자기? 5년 동안 amazon 이나 ubuntu 만 썼었는데 갑자기 centos7 이라... 뭐 tomcat 만 쓰면되니 상관없지. 


server.xml 설정하려는데 뭐꼬 파일 어데갔노. 검색해보니 centos 홈디렉토리에다가 tomcat 을 바이너리 설치해놨네... ㅋㅋ (여기서 살짝 당황) 뭐 돌아가기만 하면 되니.


근데 뭔가 이상... 버전을 보니 tomcat7 두둥~. 이게 머하자는... 뭐 tomcat7 을 써도 되지만 굳이? 서버 관리자들이란 지들이 만드는거에 태클거는거를 좋아하지 않지만 그래도 이것만은... 정중하게 부탁했다. tomcat8 깔아줘요잉~ 곧 피드백이 왔다.


server.xml 바꾸고 톰캣 재부팅하려고 하는데 바이너리 설치해놔서 아무것도 되는게 없음. /etc/init.d, chkconfig, service, (아.. 아재...ㅋㅋ) 여기부터 슬슬 짜증이 났음. (패키지 설치했으면 끝날일을 더럽게 귀찮게 하네...)


tomcat.service 만들고 구동 user 를 tomcat 으로 지정하는 순간이 바로 삽질의 시작.


# systemctl start tomcat

Job for tomcat.service failed because the control process exited with error code. See "systemctl status tomcat.service" and "journalctl -xe" for details.


# systemctl status tomcat

Process: 14 ExecStart=/home/centos/tomcat8/bin/startup.sh (code=exited, status=203/EXEC)

tomcat.service - Apache Tomcat Web Application Container

Loaded: loaded (/etc/systemd/system/tomcat.service; enabled; vendor preset: disabled)

Active: activating (auto-restart) (Result: exit-code) 


systemd[1]: Starting Apache Tomcat Web Application Container...

systemd[1]: tomcat.service: Control process exited, code=exited status=203

systemd[1]: Failed to start Apache Tomcat Web Application Container.

systemd[1]: tomcat.service: Unit entered failed state.

systemd[1]: tomcat.service: Failed with result 'exit-code'.


# journalctl -xe

tomcat.service: Failed at step EXEC spawning /home/centos/tomcat8/bin/startup.sh: Permission denied


응?? 웬 퍼미션 문제. tomcat 홈디렉토리는 tomcat 이 소유자였고 bin 디렉토리의 명령어들 역시 실행 권한이 주어져 있었다. 음... 뭐가 문제일까. 일단 권한 문제가 없는 것은 확인했고 저 203 code 의 에러가 몹시 거슬렸다. 검색해 보니 java 버전 확인과 실행 권한을 주라는 말이 대부분이었다. 일단 생성한 tomcat.service 파일을 꼼꼼히 봤다. 모든 경로, 모든 설정이 문제 없었다.


여기서 갑자기 든 생각. 이미 root 권한으로 생성된 webapps 디렉토리, log 파일들이 구동시 권한문제를 일으킬 수도 있다는 생각에 그것들도 다 삭제했다. 하지만  이놈에 tomcat 은 실행될 생각이 없다.


tomcat user 를 root 로 바꾸니 정상구동. tomcat 으로 바꾸면 에러. 어짜피 해볼만한건 이제 다해봤고 바이너리 설치니 디렉토리를 다른데로 옮겨보자 안되면 재설치하고... 그러고 /usr/local 로 옮겼는데 두둥!!! 된다!!! 뭔데 이거. 다른 사용자 디렉토리에 톰캣 설치한게 문제였던거야.


아니 의심은 했는데, 사용자 디렉토리에 톰캣 풀어논거 보고 어이가 없긴 했는데, 권한만 주면 문제없을꺼라고 생각한 내가 문제인건가? 지금도 너무 어이없음. 내가 초보자 된 느낌. 이것저것 다해서 총 6시간 삽질. 일단 되는건 봤고 너무 지저분해져서 똑같은 os 이미지로 구동시켜서 tomcat 서버 하나 만들어봤다.


yum update

yum search java-1

yum install java-1.8.0-openjdk

yum install wget

wget https://harbottle.gitlab.io/harbottle-main/7/x86_64/harbottle-main-release.rpm

rpm -Uvh harbottle-main-release.rpm

yum install tomcat8


10분 걸렸으려나... 이렇게 해줬으면 이미 끝났을 일을 가지고... ㅂㄷㅂㄷ. 이렇게 줘놓고 너희들은 편하게 쉬고 있었겠지. 후아~ 다음번 서버 요청할게 더 무섭다. 위처럼 타이핑 할 명령어들까지 전달을 해줘야 하나. 그런거야??


그래도 이런 이상한 세팅 때문에 6시간 동안 하나 배웠다. 다른 사용자 디렉토리에서 톰캣은 구동되지 않는다는 사실. 죽기전에 한번 써먹을 데가 있으려나...




WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,



요즘 리눅스 문서에 apt-get 대신 apt 를 주로 사용하는 것 같아 검색해 보니, apt-get 을 사용하면 아재라는...;;; man 페이지를 찾아보면,


 apt-get 

apt-get 나 apt-cache 등은 알다시피 RPM 기반 배포판에서 사용되는 APT 패키지 핸들링 도구들이고,


 apt 

Advanced Package Tool 의 약자로 high-level 의 고급 패키지 도구이다. 최종 사용자를 위해 개발되고 apt-get 나 apt-cache 를 대체한다.


다른 프로그램이지만 apt 를 apt-get 과 apt-cache 의 alias 정도로 간주하고 사용해도 무방할 듯 싶다. 저수준 옵션들을 완벽하게 지원하지는 않지만, apt 역시 지속적으로 개발되고 있으니, apt-get 과 apt-cache 를 직접 사용할 일은 점점 더 적어질 것이다. 


apt 가 나온 이유는 apt-get 과 apt-cache 의 명령 더 편하게 사용하라고 나온 것이다. 4자에서 5자리를 덜 쓰게 해주는 편의와 stdout 에서의 컬러풀함? 쓰지 않을 이유가 없다.ㅎ




WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,



Linux 상에서의 Minikube 도 설치 방법이 여러가지이다. 우선 하이퍼바이저 상에서 Minikube 를 구동할 것인지, 호스트에서 직접 구동할 것인지를 선택해야 한다. 하이퍼바이저를 이용한다면 리소스를 더 알뜰히 사용할 수 있겠지만, 모든 리눅스에서 하이퍼바이저를 사용할 수는 없다. Widnows 편에서 말했듯이 CPU 의 가상화(VT-x/AMD-v) 지원과 Bios 에서 가상화 활성화 상태를 확인해야 하는데, 요즘 많이들 사용하는 클라우드 컴퓨팅 서비스(EC2, GCE) 등에서는 대부분 HVM 가상화를 사용하고 있고, 그 자체가 이미 VM 이므로 그들은 Bios 에 접근을 할 수 없다. 결국 클라우드 컴퓨팅에서는 하이퍼바이저를 사용할 수 없으므로 과감히 VM 사용을 포기한다.ㅠ 현재 상황이 Linux 에서 VM 을 돌리기 위해 멀쩡한 PC 들에 Linux 를 까기는 좀;; 아무튼 현재 상황에서는 Linux 에서 VM 없이 호스트에서 Minikube 를 직접 구동시켜는 방법을 사용해야 하며, VM 없이 Minikube 를 시작하는 명령은...


 # minikube start --vm-driver=none 


하지만 EC2 Linux 에서도 minikube 를 정상적으로 구동하기 위해 체크해야 할 것들이 있다.



Minikube 구동시 체크사항


  1. 2cpu, 2GB 메모리, 20GB 디스크 이상의 사양.
    EC2 에서 free-tier 인 t2.micro 는 1cpu, 1G 메모리로, minikube 를 구동할 수 없다. 최소 t2.medium 사양(2cpu, 4GB mem)이 필요하다.

  2. docker 설치(Container Runtime)와 cgroup driver 매칭
    docker 가 반드시 필요하며(docker.io 나 docker-ce), 설치 후 docker info | grep -i cgroup 명령으로 cgroup driver 가 cgroupfs 인지 systemd 인지 확인해야 한다. minikube 구동 후에 kubelet 의 cgroup driver 와 일치하지 않는 다면 관련을 참고하여 일치시킨다. VM 에서 구동시에는 docker 가 자동 설치되며 자동 매칭을 해준 부분이다.

  3. 구동 실패시 클러스터 삭제
    minikube start 로 클러스터가 생성되다가 에러가 발생하면 캐싱으로 인해 에러가 반복될 수 있다. 다시 구동하기 전에는 minikube delete 명령으로 생성된 클러스터를 제거해 준다.



EC2 에서 발생할 수 있는 에러 메시지


- virtualbox 미설치 메시지

# minikube start

o   minikube v0.35.0 on linux (amd64)

>   Creating virtualbox VM (CPUs=2, Memory=2048MB, Disk=20000MB) ...

@   Downloading Minikube ISO ...

 184.42 MB / 184.42 MB [============================================] 100.00% 0s

!   Unable to start VM: create: precreate: VBoxManage not found. Make sure VirtualBox is installed and VBoxManage is in the path


- 가상화 비활성화 메시지

# minikube start

o   minikube v0.35.0 on linux (amd64)

>   Creating virtualbox VM (CPUs=2, Memory=2048MB, Disk=20000MB) ...

!   Unable to start VM: create: precreate: This computer doesn't have VT-X/AMD-v enabled. Enabling it in the BIOS is mandatory


- docker 미설치 메시지

# minikube start --vm-driver=none

i   This can also be done automatically by setting the env var CHANGE_MINIKUBE_NONE_USER=true

>   Creating none VM (CPUs=2, Memory=2048MB, Disk=20000MB) ...

!   Unable to start VM: create: precreate: exec: "docker": executable file not found in $PATH


- cgroup driver 불일치 메시지

# minikube start --vm-driver=none

This error is likely caused by:

- The kubelet is not running

- The kubelet is unhealthy due to a misconfiguration of the node in some way (required cgroups disabled)



EC2 (ubuntu) 에서 minikube 구동 성공


# minikube start --vm-driver=none

o   minikube v0.35.0 on linux (amd64)

>   Configuring local host environment ...


!   The 'none' driver provides limited isolation and may reduce system security and reliability.

!   For more information, see:

-   https://github.com/kubernetes/minikube/blob/master/docs/vmdriver-none.md


!   kubectl and minikube configuration will be stored in /root

!   To use kubectl or minikube commands as your own user, you may

!   need to relocate them. For example, to overwrite your own settings:


    - sudo mv /root/.kube /root/.minikube $HOME

    - sudo chown -R $USER $HOME/.kube $HOME/.minikube


i   This can also be done automatically by setting the env var CHANGE_MINIKUBE_NONE_USER=true

>   Creating none VM (CPUs=2, Memory=2048MB, Disk=20000MB) ...

-   "minikube" IP address is 10.0.1.121

-   Configuring Docker as the container runtime ...

-   Preparing Kubernetes environment ...

-   Pulling images required by Kubernetes v1.13.4 ...

-   Launching Kubernetes v1.13.4 using kubeadm ...

:   Waiting for pods: apiserver proxy etcd scheduler controller addon-manager dns

-   Configuring cluster permissions ...

-   Verifying component health .....

+   kubectl is now configured to use "minikube"

=   Done! Thank you for using minikube!

root@ip-10-0-1-121:~# minikube status

host: Running

kubelet: Running

apiserver: Running

kubectl: Correctly Configured: pointing to minikube-vm at 10.0.1.121




WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,

Tomcat 80 to 443 port

Server/AWS 2018. 8. 8. 12:42

미션. http://mydomain.com -> https://mydomain.com


간만에 톰캣 단독 서버를 만들면서 포트 포워딩에 대한 노가다를 해보았다.

톰캣은 기본적으로 8080 포트와 8443(SSL) 포트를 사용하기 때문에 대부분의 경우 80 포트나 443 포트로 변경하기를 원할 것이다.

도커 등의 각종 컨테이너 서비스를 사용하면 포트 걱정할 일은 없지만, 포트 포워딩이 아닌 포트 변경이 가능한 방법을 찾아봤다.


> server.xml 


<Connector port="8080" protocol="HTTP/1.1" ... redirectPort="8443" ...
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol" ...
cs


톰캣이 실행중일 때 netstat 로 listen 중인 포트를 확인해 보면 8080, 8443 포트가 열려 있는 것을 확인할 수 있다.

server.xml 파일에 설정되어 있는 포트 때문인데, 이 포트들을 원하는 포트로 변경한다고 해서 모두 동작하지는 않는다.

1024 이하의 TCP/UDP 포트(well-known) 로 변경하려 할 경우 root 권한을 필요로 하기 때문에 기본 세팅으로는 well-known 포트로 변경 할 수 없다.

(이를 가능하게 하는 것이 authbind 이다.)


이러한 이유로 우리는 tomcat 유저로 톰캣을 실행시킬 경우 포트를 80 이나 443 등으로 바꾸려는 무모한 짓으로 시간을 낭비하지 말아야 한다.

이를 확인하려면 tomcat8.conf 파일의 TOMCAT_USER 를 root 로 설정하면 server.xml 에 설정한 대로 포트가 변경되는 것을 확인할 수 있다.

하지만 운용시 생성되는 모든 파일, 배포 디렉토리 및 log 파일까지 모두 root 로 설정되기 때문에 일반 유저로는 접근할 수 없어 좋은 방법이 될 수 없다.

그 어떤 서비스도 해당 그룹과 권한을 설정하여 사용하지, root 로 실행하라고 권하는 서비스는 없다.


결국 깔끔한 방법은 포트 포워딩이다.



80->8080, 443->8443 포트 포워딩


$ sudo vi /etc/init.d/iptables 
iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 8080
iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 443 -j REDIRECT --to-port 8443
 
$ sudo /etc/init.d/iptables restart
cs


이렇게 iptables 로 포트 포워딩을 하면 80 과 443 을 사용할 수 있다.


http://mydomain.com (80)   -> http://mydomain.com (8080)

https://mydomain.com (443) -> https://mydomain.com (8443)


iptables 대신 firewalld 를 사용할 수도 있다.


$ sudo firewall-cmd --zone=public --add-forward-port=port=80:proto=tcp:toport=8080 --permanent
$ sudo firewall-cmd --zone=public --add-forward-port=port=443:proto=tcp:toport=8443 --permanent $ sudo firewall-cmd --reload
cs



80->443 포트 포워딩


이 상태에서 80 포트으로 접속했을 때 무조건 443 포트로 포워딩하려면 web.xml 파일을 수정한다.


$ sudo /etc/tomcat8/web.xml
      ...
      <security-constraint>
            <web-resource-collection>
                  <web-resource-name>Automatic SSL Forward</web-resource-name>
                  <url-pattern>/*</url-pattern>
            </web-resource-collection>
            <user-data-constraint>
                  <transport-guarantee>
                        CONFIDENTIAL
                  </transport-guarantee>
            </user-data-constraint>
      </security-constraint>
 
</web-app>
cs



http://mydomain.com -> https://mydomain.com:8443


여기서 server.xml 파일의 redirectPort 를 443 으로 바꿔주면,


http://mydomain.com -> https://mydomain.com


firewalld 를 사용할 때는 http 접속시 https 로 자동변경 되지 않아 server.xml 파일에 추가 설정이 필요했다.


<Connector port="8080" redirectPort="443" ... />
<Connector port="8443" proxyPort="443" ... />
cs



8443 포트 막기


마지막으로 https://mydomain.com:8443 같은 식의 8443 포트로 직접 접근을 막기 위해 iptables 를 한번 더 수정한다.


$ sudo vi /etc/init.d/iptables 
iptables -A PREROUTING -t mangle -p tcp --dport 8443 -j DROP
 
$ sudo /etc/init.d/iptables restart
cs




WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,