diff --git a/.github/workflows/test-systemd.yml b/.github/workflows/test-systemd.yml new file mode 100644 index 0000000..64c4930 --- /dev/null +++ b/.github/workflows/test-systemd.yml @@ -0,0 +1,230 @@ +name: Test systemd Service Registration + +on: + push: + branches-ignore: + - master + workflow_dispatch: + +env: + LUCEE_INSTALLER_VERSION: 6.2.2.90-RC + INSTALL_JRE: true + +jobs: + test-systemd-ubuntu-x64: + runs-on: ubuntu-latest + needs: build-installer + strategy: + matrix: + user: [ lucee ] + steps: + - name: Download Linux Installer artifact + uses: actions/download-artifact@v4 + with: + name: lucee-installer-${{ env.LUCEE_INSTALLER_VERSION }}-linux-x64-run + + - name: Run Linux installer with startatboot=true + run: | + chmod +x lucee-${{ env.LUCEE_INSTALLER_VERSION }}-linux-x64-installer.run + sudo ./lucee-${{ env.LUCEE_INSTALLER_VERSION }}-linux-x64-installer.run \ + --mode unattended \ + --installconn false \ + --installmodcfml false \ + --installiis false \ + --startatboot true \ + --luceepass ibtest \ + --systemuser ${{ matrix.user }} \ + --installjre ${{ env.INSTALL_JRE }} + + - name: Verify systemd service file was created + run: | + echo "### Systemd Service Test Results" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + if [ -f /etc/systemd/system/lucee_ctl.service ]; then + echo "Service file created at /etc/systemd/system/lucee_ctl.service" | tee -a $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + cat /etc/systemd/system/lucee_ctl.service | tee -a $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + else + echo "ERROR: Service file NOT found at /etc/systemd/system/lucee_ctl.service" | tee -a $GITHUB_STEP_SUMMARY + exit 1 + fi + + - name: Verify service is enabled + run: | + echo "" >> $GITHUB_STEP_SUMMARY + echo "#### Service Status" >> $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + systemctl is-enabled lucee_ctl | tee -a $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + + - name: Stop Lucee started by installer (so systemd can manage it) + run: | + sudo /opt/lucee/lucee_ctl stop + sleep 2 + # Remove stale PID file if exists + sudo rm -f /opt/lucee/tomcat/work/tomcat.pid + + - name: Test systemctl start + run: | + sudo systemctl start lucee_ctl + sleep 5 + echo "" >> $GITHUB_STEP_SUMMARY + echo "#### After systemctl start" >> $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + sudo systemctl status lucee_ctl --no-pager | tee -a $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + + - name: Test Lucee is responding + run: | + echo "" >> $GITHUB_STEP_SUMMARY + sleep 10 + echo "#### Lucee Response" >> $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + curl -s http://127.0.0.1:8888/ | head -20 | tee -a $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + + - name: Test systemctl stop + run: | + sudo systemctl stop lucee_ctl + sleep 2 + echo "" >> $GITHUB_STEP_SUMMARY + echo "#### After systemctl stop" >> $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + sudo systemctl status lucee_ctl --no-pager || true | tee -a $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + + - name: Test systemctl restart + run: | + sudo systemctl start lucee_ctl + sleep 5 + sudo systemctl restart lucee_ctl + sleep 5 + echo "" >> $GITHUB_STEP_SUMMARY + echo "#### After systemctl restart" >> $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + sudo systemctl status lucee_ctl --no-pager | tee -a $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + + - name: Test service removal + run: | + sudo /opt/lucee/sys/service_config.sh --remove --name lucee_ctl + echo "" >> $GITHUB_STEP_SUMMARY + echo "#### After service removal" >> $GITHUB_STEP_SUMMARY + if [ -f /etc/systemd/system/lucee_ctl.service ]; then + echo "ERROR: Service file still exists after removal" | tee -a $GITHUB_STEP_SUMMARY + exit 1 + else + echo "Service file successfully removed" | tee -a $GITHUB_STEP_SUMMARY + fi + + - name: Test custom service name - install + run: | + echo "" >> $GITHUB_STEP_SUMMARY + echo "### Custom Service Name Test" >> $GITHUB_STEP_SUMMARY + sudo /opt/lucee/sys/service_config.sh --install --path /opt/lucee/lucee_ctl --name my_custom_lucee + + if [ -f /etc/systemd/system/my_custom_lucee.service ]; then + echo "Custom service file created at /etc/systemd/system/my_custom_lucee.service" | tee -a $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + cat /etc/systemd/system/my_custom_lucee.service | tee -a $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + else + echo "ERROR: Custom service file NOT created" | tee -a $GITHUB_STEP_SUMMARY + exit 1 + fi + + - name: Test custom service name - start + run: | + sudo systemctl start my_custom_lucee + sleep 5 + echo "" >> $GITHUB_STEP_SUMMARY + echo "#### Custom service status" >> $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + sudo systemctl status my_custom_lucee --no-pager | tee -a $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + + # Verify Lucee is responding + sleep 5 + curl -s http://127.0.0.1:8888/ | head -5 + + - name: Test custom service name - remove + run: | + sudo /opt/lucee/sys/service_config.sh --remove --name my_custom_lucee + if [ -f /etc/systemd/system/my_custom_lucee.service ]; then + echo "ERROR: Custom service file still exists after removal" | tee -a $GITHUB_STEP_SUMMARY + exit 1 + else + echo "Custom service file successfully removed" | tee -a $GITHUB_STEP_SUMMARY + fi + + - name: debug failure + if: ${{ failure() }} + run: | + echo "----- installbuilder_installer.log" + sudo cat /tmp/installbuilder_installer.log || true + echo "----- /etc/systemd/system/" + ls -la /etc/systemd/system/ | grep lucee || true + echo "----- lucee_ctl.service (if exists)" + sudo cat /etc/systemd/system/lucee_ctl.service || true + echo "----- lucee_ctl script" + sudo cat /opt/lucee/lucee_ctl || true + echo "----- catalina.out" + sudo cat /opt/lucee/tomcat/logs/catalina.out || true + echo "----- journalctl" + sudo journalctl -u lucee_ctl --no-pager || true + + build-installer: + runs-on: ubuntu-latest + env: + IB_URL: https://releases.installbuilder.com/installbuilder/installbuilder-enterprise-24.3.0-linux-x64-installer.run + IB_NAME: installbuilder-enterprise-24.3.0-linux-x64-installer.run + lucee_build_version: 6.2.2.90-RC + steps: + - uses: actions/checkout@v4 + - name: Download and Install InstallBuilder + run: | + curl ${{ env.IB_URL }} -o ${{ env.IB_NAME }} + chmod a+x ${{ env.IB_NAME }} + ./${{ env.IB_NAME }} --prefix /tmp/ib --mode unattended + - name: Set Install Builder license + env: + INSTALLBUILDER_LICENSE: ${{ secrets.INSTALLBUILDER_LICENSE }} + shell: bash + run: | + echo "$INSTALLBUILDER_LICENSE" >> lucee/license.xml + - name: Download Lucee Jar + run: | + curl --fail https://cdn.lucee.org/lucee-${{ env.LUCEE_INSTALLER_VERSION }}.jar -o lucee-${{ env.LUCEE_INSTALLER_VERSION }}.jar -s + mv lucee-${{ env.LUCEE_INSTALLER_VERSION }}.jar lucee/lucee/lib/ + - name: Cache Maven packages + uses: actions/cache@v4 + with: + path: ~/.m2 + key: lucee-script-runner-maven-cache + - name: Download latest Tomcat and Java + uses: lucee/script-runner@main + with: + webroot: ${{ github.workspace }}/ + execute: /download-latest-java-tomcat.cfm + luceeVersion: ${{ env.lucee_build_version }} + - name: Prepare Tomcat Linux + run: | + cd lucee/tomcat9/ + rm -rf tomcat + cd ../.. + mv src-tomcat/linux lucee/tomcat9/tomcat + cp -ar lucee/tomcat9/tomcat-lucee-conf/* lucee/tomcat9/tomcat + - name: Build Lucee Installer - Linux x86 x64 + run: | + cd lucee + /tmp/ib/bin/builder build lucee.xml linux-x64 --verbose --license license.xml + - name: Upload Artifact - Linux Installer x86 + uses: actions/upload-artifact@v4 + with: + name: lucee-installer-${{ env.LUCEE_INSTALLER_VERSION }}-linux-x64-run + path: /tmp/ib/output/*linux-x64-installer.run + retention-days: 1 + compression-level: 0 diff --git a/lucee/linux/sys/service_config.sh b/lucee/linux/sys/service_config.sh index bc11e41..1dbf1ea 100755 --- a/lucee/linux/sys/service_config.sh +++ b/lucee/linux/sys/service_config.sh @@ -21,9 +21,10 @@ # History: 1.0 - Initial Release # 1.1 - Added Runlevel 2 to default Ubuntu start # 1.2 - Added defaulting to redhat system for compatibility +# 1.3 - Added systemd support and Arch Linux detection ############################################################################### -version=1.2 +version=1.3 progname=$(basename $0) basedir=$( cd "$( dirname "$0" )" && pwd ); @@ -120,7 +121,7 @@ while [ $# -gt 0 ]; do ;; -r|--remove) myMode="remove" - shift 2 + shift ;; -p|--path) myPath=$2 @@ -346,7 +347,7 @@ function test_updateRCD { # didn't find update-rc.d, can we install it with apt? if [[ -z $aptInstallAttempt ]] || [[ $aptInstallAttempt -eq 0 ]]; then - + # set the install attempted variable to "no" aptInstallAttempt=0; detectAPTExists; @@ -369,13 +370,103 @@ function test_updateRCD { fi } +function is_systemd { + # Check if systemd is the init system + # Returns 0 (true) if systemd, 1 (false) otherwise + if [[ -d /run/systemd/system ]]; then + return 0 + fi + return 1 +} + +function get_lucee_install_dir { + # Extract the install directory from the lucee_ctl script path + # e.g. /opt/lucee/lucee_ctl -> /opt/lucee + dirname "$(realpath "$myPath")" +} + +function install_systemd_service { + echo "* [INFO]: Detected systemd init system."; + + local installDir=$(get_lucee_install_dir) + local serviceFile="/etc/systemd/system/${myServiceName}.service" + local scriptPath=$(realpath "$myPath") + + # Extract the TOMCAT_OWNER from the lucee_ctl script + local serviceUser=$(grep -oP 'TOMCAT_OWNER=\K[^;]+' "$scriptPath" | head -1) + if [[ -z "$serviceUser" ]]; then + serviceUser="root" + fi + + echo "* [INFO]: Creating systemd service file at ${serviceFile}"; + echo "* [INFO]: Service will run as user: ${serviceUser}"; + + # Create the systemd unit file + cat > "$serviceFile" << EOF +[Unit] +Description=Lucee/Tomcat CFML Application Server (${myServiceName}) +After=network.target + +[Service] +Type=forking +User=${serviceUser} +PIDFile=${installDir}/tomcat/work/tomcat.pid +ExecStart=${scriptPath} start +ExecStop=${scriptPath} stop +ExecReload=${scriptPath} restart +Restart=on-failure +TimeoutStartSec=60 +TimeoutStopSec=60 + +[Install] +WantedBy=multi-user.target +EOF + + chmod 644 "$serviceFile" + + # Reload systemd and enable the service + echo "* [INFO]: Reloading systemd daemon..."; + systemctl daemon-reload + + echo "* [INFO]: Enabling ${myServiceName} service..."; + systemctl enable "$myServiceName" +} + +function remove_systemd_service { + echo "* [INFO]: Detected systemd init system."; + + local serviceFile="/etc/systemd/system/${myServiceName}.service" + + if [[ -f "$serviceFile" ]]; then + echo "* [INFO]: Stopping ${myServiceName} service..."; + systemctl stop "$myServiceName" 2>/dev/null || true + + echo "* [INFO]: Disabling ${myServiceName} service..."; + systemctl disable "$myServiceName" 2>/dev/null || true + + echo "* [INFO]: Removing systemd service file..."; + rm -f "$serviceFile" + + echo "* [INFO]: Reloading systemd daemon..."; + systemctl daemon-reload + else + echo "* [INFO]: Service file not found at ${serviceFile}, nothing to remove."; + fi +} + function install_luceeCTL { - # start out by seeing what kind of system we're on + # Check for systemd first - this is the modern way and works on all current distros + if is_systemd; then + install_systemd_service + return + fi + + # Fall back to legacy init.d for older systems getLinuxVersion; # now see what commands we need to run based on the system type if [[ $myLinuxVersion == *RedHat* ]]; then - echo "* [INFO]: Detected RedHat-based build."; + echo "* [INFO]: Detected RedHat-based build (legacy init)."; test_chkconfig; # copy lucee_ctl to /etc/init.d/ @@ -386,7 +477,7 @@ function install_luceeCTL { chkconfig $myServiceName on elif [[ $myLinuxVersion == *Debian* ]]; then - echo "* [INFO]: Detected Debian-based build."; + echo "* [INFO]: Detected Debian-based build (legacy init)."; test_updateRCD; # copy lucee_ctl to /etc/init.d/ @@ -396,7 +487,7 @@ function install_luceeCTL { # install service update-rc.d $myServiceName start 10 2 3 4 5 . stop 10 0 . else - echo "* [INFO]: Unable to detect OS, defaulting to RedHat."; + echo "* [INFO]: Unable to detect OS, defaulting to RedHat (legacy init)."; test_chkconfig; # copy lucee_ctl to /etc/init.d/ @@ -409,25 +500,31 @@ function install_luceeCTL { } function remove_luceeCTL { - # start out by seeing what kind of system we're on + # Check for systemd first + if is_systemd; then + remove_systemd_service + return + fi + + # Fall back to legacy init.d for older systems getLinuxVersion; # now see what commands we need to run based on the system type if [[ $myLinuxVersion == *RedHat* ]]; then - echo "* [INFO]: Detected RedHat-based build."; + echo "* [INFO]: Detected RedHat-based build (legacy init)."; test_chkconfig; # remove the service chkconfig $myServiceName off elif [[ $myLinuxVersion == *Debian* ]]; then - echo "* [INFO]: Detected Debian-based build."; + echo "* [INFO]: Detected Debian-based build (legacy init)."; test_updateRCD; # remove service update-rc.d -f $myServiceName remove else - echo "* [INFO]: Unable to detect OS, defaulting to RedHat."; + echo "* [INFO]: Unable to detect OS, defaulting to RedHat (legacy init)."; test_chkconfig; # remove the service