My setup uses systemd Socket Activation which you can read more about on Lennart Poettering's website.
The following link has been used as a basis for that setup: systemd: on-demand start of services like postgresql and mysql that do not yet support socket-based activation.
I took Amazon Linux distribution for this demo with the following kernel: 4.14.123-111.109.amzn2.x86_64, however, the setup steps should be the same for any other Red Hat based distributions.
The Oracle Database version is 19.3.
In a nutshell, we need to create several systemd units:
1. /etc/systemd/system/proxy-to-oracle.socket:
[Unit] Description="Socket for Oracle Socket Proxy" Documentation=https://www.freedesktop.org/software/systemd/man/systemd-socket-proxyd.html [Socket] ListenStream=0.0.0.0:1522 [Install] WantedBy=sockets.targetThe socket listens on port 1522 which accepts client connections to the database. When a connection comes, it starts the following service if it's not already running:
2. /etc/systemd/system/proxy-to-oracle.service:
[Unit] Description="Oracle Socket Proxy" Documentation=https://www.freedesktop.org/software/systemd/man/systemd-socket-proxyd.html Requires=dbora.service After=dbora.service [Service] User=nobody Group=nobody ExecStart=/lib/systemd/systemd-socket-proxyd ip-172-17-31-208.ec2.internal:1521 Restart=on-failure PrivateTmp=trueI am using systemd-socket-proxyd that proxies the connection to the host ip-172-17-31-208.ec2.internal on port 1521 - it's just the hostname/port of the server where the listener is running (I'm using the same machine to host all services).
There are After and Requires dependencies on dbora.service, which manages the database and the listener.
3. /etc/systemd/system/dbora.service:
[Unit] Description="The Oracle Database Service" After=syslog.target network.target [Service] LimitMEMLOCK=infinity LimitNOFILE=65535 RemainAfterExit=yes User=oracle Group=dba ExecStart=/home/oracle/scripts/start_oracle.sh ExecStop=/u01/app/oracle/product/19/dbhome_1/bin/dbshut /u01/app/oracle/product/19/dbhome_1 [Install] WantedBy=multi-user.targetIn the service above, I used the standard stop command and a slightly changed startup script: start_oracle.sh:
#!/bin/sh export ORACLE_SID=orcl ORAENV_ASK=NO . /usr/local/bin/oraenv -s sqlplus / as sysdba <<_EOF startup _EOF lsnrctl start sqlplus / as sysdba <<_EOF alter system register; _EOFI did not use the dbstart command as it starts the listener first before bringing up databases. I was getting ORA-01109: database not open errors with the standard dbstart script, so I resorted to my own version of the startup script. The TNS-descriptor is below:
pdb = (DESCRIPTION= (RETRY_COUNT=10) (RETRY_DELAY=10) (ADDRESS= (PROTOCOL=TCP)(HOST=ip-172-17-31-208.ec2.internal)(PORT=1522) ) (CONNECT_DATA= (SERVICE_NAME=pdb) ) )It's worth mentioning that the port is set to 1522 - that is where the systemd proxy is listening on. I use a non-standard client sqlnet.ora file that disables Out of Band Break (see more information about it: What is DISABLE_OOB (Out Of Band Break)? (Doc ID 373475.1)):
DISABLE_OOB=ONWithout that, I kept getting the ORA-12637: Packet receive failed error. I searched through SQL*Net traces and finally found a clue that pointed out to that parameter disabling Out of Band Breaks. Actually, I do not recall that I got that error when I configured a similar setup on Oracle Database 12.1 and Oracle Linux 6 last year. I'm going to connect to the socket on port 1522; the proxy-to-oracle.service should start the dbora.service if it is not running, and proxy the connection to the listener. There is a little helper script to test the database connection that writes some output to estimate how long it takes to establish the connection:
-- test_db_conn.sh #!/bin/sh export TNS_ADMIN="${HOME}/tns_admin" echo "Started at: "$(date +"%F %T") sqlplus -L tc/tc@pdb <<_EOF select to_char(sysdate, 'yyyy-mm-dd hh24:mi:ss') current_date from dual; _EOF echo "" echo "Finished at: "$(date +"%F %T")The initial state of services is below - only the proxy-to-oracle.socket is running:
# systemctl status proxy-to-oracle.socket proxy-to-oracle.service dbora.service ● proxy-to-oracle.socket - "Socket for Oracle Socket Proxy" Loaded: loaded (/etc/systemd/system/proxy-to-oracle.socket; enabled; vendor preset: disabled) Active: active (listening) since Thu 2019-08-08 13:31:19 UTC; 20h ago Docs: https://www.freedesktop.org/software/systemd/man/systemd-socket-proxyd.html Listen: 0.0.0.0:1522 (Stream) ● proxy-to-oracle.service - "Oracle Socket Proxy" Loaded: loaded (/etc/systemd/system/proxy-to-oracle.service; static; vendor preset: disabled) Active: inactive (dead) since Fri 2019-08-09 10:25:21 UTC; 3min 15s ago Docs: https://www.freedesktop.org/software/systemd/man/systemd-socket-proxyd.html Process: 16042 ExecStart=/lib/systemd/systemd-socket-proxyd ip-172-17-31-208.ec2.internal:1521 (code=killed, signal=TERM) Main PID: 16042 (code=killed, signal=TERM) ● dbora.service - "The Oracle Database Service" Loaded: loaded (/etc/systemd/system/dbora.service; enabled; vendor preset: disabled) Active: inactive (dead) since Fri 2019-08-09 10:25:46 UTC; 2min 50s ago Process: 22234 ExecStop=/u01/app/oracle/product/19/dbhome_1/bin/dbshut /u01/app/oracle/product/19/dbhome_1 (code=exited, status=0/SUCCESS) Process: 16032 ExecStart=/home/oracle/scripts/start_oracle.sh (code=exited, status=0/SUCCESS) Main PID: 16032 (code=exited, status=0/SUCCESS)Neither the instance nor the listener are running:
[oracle@ip-172-17-31-208 ~]$ pgrep -af 'pmon|tnslsnr' [oracle@ip-172-17-31-208 ~]$Now I am starting the script that tests the database connection:
[oracle@ip-172-17-31-208 scripts]$ ./test_db_conn.sh Started at: 2019-08-09 10:32:53 SQL*Plus: Release 19.0.0.0.0 - Production on Fri Aug 9 10:32:53 2019 Version 19.3.0.0.0 Copyright (c) 1982, 2019, Oracle. All rights reserved. Last Successful login time: Fri Aug 09 2019 09:27:45 +00:00 Connected to: Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production Version 19.3.0.0.0 SQL> 2 CURRENT_DATE ------------------- 2019-08-09 10:33:13 SQL> Disconnected from Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production Version 19.3.0.0.0 Finished at: 2019-08-09 10:33:14It takes less than 20 seconds to start the instance (the TNS descriptor used RETRY_DELAY=10, so that the client tries to establish a connection every 10 seconds).