본문으로 바로가기

1. ROOT 계정

1. server.xml 파일 수정

  • vi, vim (편집 툴)로 설정 파일을 편집 모드로 접근합니다.
  • 톰캣경로/conf/server.xml
# vi apache-tomcat-8.5.54/conf/server.xml
  • 약 69번 줄에 있는 Connector의 port를 80으로 수정합니다.
 69     <Connector port="8080" protocol="HTTP/1.1"
 70                connectionTimeout="20000"
 71                redirectPort="8443" />

 

2. 실행 및 확인

  • 프로세스와 포트를 확인합니다.
# sh apache-tomcat-8.5.54/bin/startup.sh

# ps -ef | grep tomcat | grep -v grep
root      3916     1  9 16:01 pts/3    00:00:02 /usr/bin/java -Djava.util.logging.config.file=/root/apache-tomcat-8.5.54/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 -Dignore.endorsed.dirs= -classpath /root/apache-tomcat-8.5.54/bin/bootstrap.jar:/root/apache-tomcat-8.5.54/bin/tomcat-juli.jar -Dcatalina.base=/root/apache-tomcat-8.5.54 -Dcatalina.home=/root/apache-tomcat-8.5.54 -Djava.io.tmpdir=/root/apache-tomcat-8.5.54/temp org.apache.catalina.startup.Bootstrap start

# netstat -ntap | grep LISTEN | grep 80
tcp6       0      0 127.0.0.1:8005          :::*                    LISTEN      3916/java
tcp6       0      0 :::80                   :::*                    LISTEN      3916/java

 

2. 일반 계정

1. server.xml 파일 수정

  • vi, vim (편집 툴)로 설정 파일을 편집 모드로 접근합니다.
  • 톰캣경로/conf/server.xml
# vi apache-tomcat-8.5.54/conf/server.xml
  • 약 69번 줄에 있는 Connector의 port를 80으로 수정합니다.
 69     <Connector port="80" protocol="HTTP/1.1"
 70                connectionTimeout="20000"
 71                redirectPort="8443" />

 

2. 실행 및 확인

  • 프로세스와 포트를 확인합니다.
# sh apache-tomcat-8.5.54/bin/startup.sh

$ ps -ef | grep tomcat | grep -v grep
tomcat       4101     1 37 16:07 pts/2    00:00:02 /usr/bin/java -Djava.util.logging.config.file=/home/ tomcat/apache-tomcat-8.5.54/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 -Dignore.endorsed.dirs= -classpath /home/ tomcat/apache-tomcat-8.5.54/bin/bootstrap.jar:/home/ tomcat/apache-tomcat-8.5.54/bin/tomcat-juli.jar -Dcatalina.base=/home/ tomcat/apache-tomcat-8.5.54 -Dcatalina.home=/home/ tomcat/apache-tomcat-8.5.54 -Djava.io.tmpdir=/home/ tomcat/apache-tomcat-8.5.54/temp org.apache.catalina.startup.Bootstrap start

$ netstat -ntap | grep LISTEN | grep 80
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
tcp6       0      0 127.0.0.1:8005          :::*                    LISTEN      4101/java

 

3. 문제 발생

  • 80 포트가 LISTEN 되지 않은 것을 확인할 수 있습니다.
  • 톰캣 로그를 확인해봅니다.
$ tail -n 50 apache-tomcat-8.5.54/logs/catalina.out

07-Apr-2022 16:07:47.909 심각 [main] org.apache.catalina.core.StandardService.initInternal Failed to initialize connector [Connector[HTTP/1.1-80]]
        org.apache.catalina.LifecycleException: 프로토콜 핸들러 초기화가 실패했습니다.
                at org.apache.catalina.connector.Connector.initInternal(Connector.java:1060)
                at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:136)
                at org.apache.catalina.core.StandardService.initInternal(StandardService.java:552)
                at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:136)
                at org.apache.catalina.core.StandardServer.initInternal(StandardServer.java:848)
                at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:136)
                at org.apache.catalina.startup.Catalina.load(Catalina.java:639)
                at org.apache.catalina.startup.Catalina.load(Catalina.java:662)
                at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
                at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
                at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
                at java.base/java.lang.reflect.Method.invoke(Method.java:566)
                at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:303)
                at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:473)
        Caused by: java.net.SocketException: 허가 거부
                at java.base/sun.nio.ch.Net.bind0(Native Method)
                at java.base/sun.nio.ch.Net.bind(Net.java:459)
                at java.base/sun.nio.ch.Net.bind(Net.java:448)
                at java.base/sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:227)
                at java.base/sun.nio.ch.ServerSocketAdaptor.bind(ServerSocketAdaptor.java:80)
                at org.apache.tomcat.util.net.NioEndpoint.bind(NioEndpoint.java:221)
                at org.apache.tomcat.util.net.AbstractEndpoint.init(AbstractEndpoint.java:1118)
                at org.apache.tomcat.util.net.AbstractJsseEndpoint.init(AbstractJsseEndpoint.java:223)
                at org.apache.coyote.AbstractProtocol.init(AbstractProtocol.java:587)
                at org.apache.coyote.http11.AbstractHttp11Protocol.init(AbstractHttp11Protocol.java:74)
                at org.apache.catalina.connector.Connector.initInternal(Connector.java:1058)
                ... 13 more

 

org.apache.catalina.core.StandardService.initInternal Failed to initialize connector [Connector[HTTP/1.1-80]]

라는 에러가 발생함을 알 수 있습니다.

 

원인

LISTEN이 안 되는 이유로는 유닉스 계열은 특권 포트(1~1024)를 이용하기 위해서는 반드시 root 권한이 필요합니다.

 

3. 일반 계정 해결 방법

[해결 방안]

1) iptables를 이용하여 80으로 들어온 요청을 8080으로 리다이렉트
2) jsvc 사용하여 root 권한으로 일부 권한 작업 (예 : 포트 <1024)에 바인딩 한 다음 권한이 없는 사용자에게 ID를 전환

 

본 게시물에서는 jsvc를 사용하여 해결해보겠습니다.

 

1. 자바 경로 확인 (jdk)

  • jsvc 설치를 위해서는 자바의 경로가 필요합니다.
$ which java
/usr/bin/java

$ ll /usr/bin/java
lrwxrwxrwx. 1 root root 22  4월  7 15:50 /usr/bin/java -> /etc/alternatives/java

[심볼릭 링크일 경우 다음과 같이 실제 경로 조회]
$ readlink -f /usr/bin/java
/usr/lib/jvm/java-11-openjdk-11.0.14.1.1-1.el7_9.x86_64/bin/java

 

2. 환경 변수 설정

  • 이미 설정되어 있거나 경로를 그대로 컴파일 시 사용할 거라면 생략해도 됩니다.
$ echo $JAVA_HOME

$ vi /etc/profile
export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-11.0.14.1.1-1.el7_9.x86_64

$ source /etc/profile

$ echo $JAVA_HOME
/usr/lib/jvm/java-11-openjdk-11.0.14.1.1-1.el7_9.x86_64

 

3. jsvc 컴파일 설치

  • jsvc 컴파일 설치 관련 파일은 tomcat 설치 경로의 bin 디렉터리에 포함되어 있습니다.
  • bin/commons-daemon-native.tar.gz
$ cd apache-tomcat-8.5.54/bin/

$ ls
bootstrap.jar       catalina.sh  commons-daemon-native.tar.gz  configtest.sh  digest.sh         shutdown.bat  startup.sh            tool-wrapper.bat  version.sh
catalina-tasks.xml  ciphers.bat  commons-daemon.jar            daemon.sh      setclasspath.bat  shutdown.sh   tomcat-juli.jar       tool-wrapper.sh
catalina.bat        ciphers.sh   configtest.bat  

$ tar xzvf commons-daemon-native.tar.gz

$ cd commons-daemon-1.2.2-native-src/unix

$ ./configure --with-java=$JAVA_HOME
*** Current host ***
checking build system type... x86_64-pc-linux-gnu
checking host system type... x86_64-pc-linux-gnu
checking cached host system type... ok
... 생략
*** All done ***
Now you can issue "make"

$ make
(cd native; make  all)
make[1]: Entering directory `/home/tomcat/apache-tomcat-8.5.54/bin/commons-daemon-1.2.2-native-src/unix/native'
gcc -g -O2 -DOS_LINUX -DDSO_DLFCN -DCPU=\"amd64\" -Wall -Wstrict-prototypes   -I/usr/lib/jvm/java-11-openjdk-11.0.14.1.1-1.el7_9.x86_64/include -I/usr/lib/jvm/java-11-openjdk-11.0.14.1.1-1.el7_9.x86_64/include/linux -c jsvc-unix.c -o jsvc-unix.o
jsvc-unix.c: In function ‘run_controller’:
jsvc-unix.c:1293:20: warning: assignment from incompatible pointer type [enabled by default]
     act.sa_handler = controller;
                    ^
... 생략
make[1]: Leaving directory `/home/tomcat/apache-tomcat-8.5.54/bin/commons-daemon-1.2.2-native-src/unix/native'

$ cp jsvc ~/apache-tomcat-8.5.54/bin/

$ cd ~/apache-tomcat-8.5.54/bin/

$ ls
bootstrap.jar       catalina.sh  commons-daemon-1.2.2-native-src  configtest.bat  digest.bat  setclasspath.bat  shutdown.sh  tomcat-juli.jar       tool-wrapper.sh
catalina-tasks.xml  ciphers.bat  commons-daemon-native.tar.gz     configtest.sh   digest.sh   setclasspath.sh   startup.bat  tomcat-native.tar.gz  version.bat
catalina.bat        ciphers.sh   commons-daemon.jar               daemon.sh       jsvc        shutdown.bat      startup.sh   tool-wrapper.bat      version.sh

 

[컴파일 설치 명령어]

configure
configure 명령어를 이용해 현재 디렉터리(설치 파일 디렉터리)에서 
configure라는 이름을 갖는 스크립트 파일을 찾고 이를 실행하여 Makefile을 생성합니다.

make
make 명령어로 생성된 Makefile을 이용하여 프로그램 코드를 컴파일하고 실행 가능한 형태로 만듭니다.

 

4. 설정

$ vi daemon.sh
  • 약 69번 줄 TOMCAT_USER=실행하고자 하는 리눅스 계정
 89 # Setup parameters for running the jsvc
 90 #
 91 test ".$TOMCAT_USER" = . && TOMCAT_USER=tomcat

 

5. 실행

  • 톰캣 실행은 root 권한으로 실행해야 합니다.
  • su 명령어를 이용하여 root 계정으로 전환하여 톰캣을 실행하거나, sudo 명령어를 이용하여 root 권한을 부여받아 톰캣을 실행합니다.
  • 실행 스크립트 파일은 daemon.sh를 사용해야 합니다.
  • daemon.sh start, daemon.sh stop
  • 로그 파일(catalina-daemon.out)
$ sudo ./daemon.sh start

또는 

$ su -
암호:

# cd /home/tomcat/apache-tomcat-8.5.54/bin/
# ./daemon.sh start

 

6. 확인

  • 프로세스를 조회해보면 두 계정으로 떠 있는 것을 확인할 수 있습니다.
  • 80 포트만 root 권한으로 열고, 그 외에 프로세스는 daemon.sh에 설정한 계정으로 실행됩니다.
$ ps -ef | grep tomcat | grep -v grep
root      7844     1  0 16:59 ?        00:00:00 jsvc.exec -java-home /usr/lib/jvm/java-11-openjdk-11.0.14.1.1-1.el7_9.x86_64 -user tomcat -pidfile /home/tomcat/apache-tomcat-8.5.54/logs/catalina-daemon.pid -wait 10 -umask 0027 -outfile /home/tomcat/apache-tomcat-8.5.54/logs/catalina-daemon.out -errfile &1 -classpath /home/tomcat/apache-tomcat-8.5.54/bin/bootstrap.jar:/home/tomcat/apache-tomcat-8.5.54/bin/commons-daemon.jar:/home/tomcat/apache-tomcat-8.5.54/bin/tomcat-juli.jar -Djava.util.logging.config.file=/home/tomcat/apache-tomcat-8.5.54/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Dignore.endorsed.dirs= -Dcatalina.base=/home/tomcat/apache-tomcat-8.5.54 -Dcatalina.home=/home/tomcat/apache-tomcat-8.5.54 -Djava.io.tmpdir=/home/tomcat/apache-tomcat-8.5.54/temp org.apache.catalina.startup.Bootstrap
tomcat    7845  7844  2 16:59 ?        00:00:02 jsvc.exec -java-home /usr/lib/jvm/java-11-openjdk-11.0.14.1.1-1.el7_9.x86_64 -user tomcat -pidfile /home/tomcat/apache-tomcat-8.5.54/logs/catalina-daemon.pid -wait 10 -umask 0027 -outfile /home/tomcat/apache-tomcat-8.5.54/logs/catalina-daemon.out -errfile &1 -classpath /home/tomcat/apache-tomcat-8.5.54/bin/bootstrap.jar:/home/tomcat/apache-tomcat-8.5.54/bin/commons-daemon.jar:/home/tomcat/apache-tomcat-8.5.54/bin/tomcat-juli.jar -Djava.util.logging.config.file=/home/tomcat/apache-tomcat-8.5.54/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Dignore.endorsed.dirs= -Dcatalina.base=/home/tomcat/apache-tomcat-8.5.54 -Dcatalina.home=/home/tomcat/apache-tomcat-8.5.54 -Djava.io.tmpdir=/home/tomcat/apache-tomcat-8.5.54/temp org.apache.catalina.startup.Bootstrap

$ netstat -ntap | grep LISTEN | grep 80
tcp6       0      0 :::80                   :::*                    LISTEN      6368/jsvc.exec