Installing Oracle 19c and then patching it is two jobs, and two outages, if you do it the old way. Since 19c, the installer can apply a Release Update to the software image before installing it (-applyRU). One silent run gives you a fully patched Oracle Home, and the database you create on it starts life at the latest RU.
This guide does the whole build from the command line: no GUI, no X11. It goes from a bare Oracle Linux server to a patched, autostarting container database. Each step ends with a check, so you always know it worked before you move on.
| Used in this guide | |
|---|---|
| OS | Oracle Linux 8 / 9 (RHEL compatible) |
| Software | Oracle Database 19c Enterprise Edition, 19.3 base image + latest RU |
| Oracle Home | /u01/app/oracle/product/19.0.0/dbhome_1 |
| Database | CDB TESTCDB with PDB TESTPDB, archivelog mode |
| Storage | /u02/oradata (datafiles), /u03/fra (fast recovery area) |
Command colour key: # as root $ as oracle SQL> as sysdba file contents
The roadmap
Prepare the OS
The preinstall RPM does the tedious OS work for you: it creates the oracle user and all the OS groups, sets kernel parameters and shell limits, and installs the required packages.
dnf -y install oracle-database-preinstall-19c # Oracle Linux 8/9 (use yum on OL7) passwd oracle id oracle # uid=54321(oracle) gid=54321(oinstall) groups=54321(oinstall),54322(dba),54323(oper), # 54324(backupdba),54325(dgdba),54326(kmdba),54330(racdba)
oracle-database-preinstall-19c from Oracle's yum server and install it with dnf, or set the kernel parameters and limits by hand from the installation guide.id oracle shows all seven groups.Directories & profile
Use one consistent layout (OFA) for everything that follows:
mkdir -p /u01/app/oracle/product/19.0.0/dbhome_1 /u01/app/oraInventory /u01/stage mkdir -p /u02/oradata /u03/fra chown -R oracle:oinstall /u01 /u02 /u03 chmod -R 775 /u01 /u02 /u03
Add the environment to the oracle user's ~/.bash_profile:
# Oracle 19c export ORACLE_SID=TESTCDB export ORACLE_BASE=/u01/app/oracle export ORACLE_HOME=$ORACLE_BASE/product/19.0.0/dbhome_1 export PATH=$ORACLE_HOME/bin:$ORACLE_HOME/OPatch:$PATH export LD_LIBRARY_PATH=$ORACLE_HOME/lib:/lib:/usr/lib umask 022
echo $ORACLE_HOME after a fresh login shows the new path.Stage the software
You need three downloads. Copy them to /u01/stage:
| File | Where to get it |
|---|---|
LINUX.X64_193000_db_home.zip | Oracle Software Delivery Cloud (edelivery) or oracle.com: the 19.3 base image |
Latest 19c Release Update, e.g. p3xxxxxxx_190000_Linux-x86-64.zip | My Oracle Support → Patches. Check Oracle's quarterly patch page for the current RU number |
| Latest OPatch (patch 6880880, release 19.0.0.0.0) | My Oracle Support. Each RU README states the minimum OPatch version |
Both edelivery and My Oracle Support offer a wget script for downloading straight to a server without a browser.
ls -lh /u01/stage shows all three zips.Unzip & refresh OPatch
In 19c the software is an image: unzip it directly into the Oracle Home. Then replace the OPatch inside that new home. -applyRU uses this OPatch, and the one shipped with 19.3 is too old for any recent RU.
cd $ORACLE_HOME unzip -oq /u01/stage/LINUX.X64_193000_db_home.zip # refresh OPatch inside the NEW home rm -rf $ORACLE_HOME/OPatch unzip -oq /u01/stage/p6880880_190000_Linux-x86-64.zip -d $ORACLE_HOME $ORACLE_HOME/OPatch/opatch version # unzip the Release Update cd /u01/stage unzip -oq p3xxxxxxx_190000_Linux-x86-64.zip # creates /u01/stage/3xxxxxxx export RU_DIR=/u01/stage/3xxxxxxx
opatch version shows the version from the RU README or newer.Response file
Keep the settings in a small response file, with every OS group mapped to its own role:
oracle.install.responseFileVersion=/oracle/install/rspfmt_dbinstall_response_schema_v19.0.0 oracle.install.option=INSTALL_DB_SWONLY UNIX_GROUP_NAME=oinstall INVENTORY_LOCATION=/u01/app/oraInventory ORACLE_HOME=/u01/app/oracle/product/19.0.0/dbhome_1 ORACLE_BASE=/u01/app/oracle oracle.install.db.InstallEdition=EE oracle.install.db.OSDBA_GROUP=dba oracle.install.db.OSOPER_GROUP=oper oracle.install.db.OSBACKUPDBA_GROUP=backupdba oracle.install.db.OSDGDBA_GROUP=dgdba oracle.install.db.OSKMDBA_GROUP=kmdba oracle.install.db.OSRACDBA_GROUP=racdba oracle.install.db.rootconfig.executeRootScript=false
dba. It works, but it gives every DBA full SYSDBA power. With the groups the preinstall RPM already created, you can grant backup, Data Guard or key-management duties separately later.Prerequisite check
$ORACLE_HOME/runInstaller -silent -executePrereqs \
-responseFile /u01/stage/db_install.rsp
Fix anything it reports (missing packages, kernel parameters, swap). Don't hide problems with -ignorePrereq.
-applyRU normally solves this. If the precheck alone still fails on OL8, the widely used workaround is export CV_ASSUME_DISTID=OL7 before running it. Oracle Linux 9 / RHEL 9 needs 19.19 or later.Install + apply RU
One command: the installer first patches the image with the RU, then installs the already-patched software. No separate opatch apply, and no second outage later.
unset ORACLE_SID
$ORACLE_HOME/runInstaller -silent -waitforcompletion \
-applyRU $RU_DIR \
-responseFile /u01/stage/db_install.rsp
# optional: add one-off patches (e.g. the matching OJVM patch) in the same run
# -applyOneOffs /u01/stage/<ojvm_patch_dir>
Preparing the home to patch...
Applying the patch /u01/stage/3xxxxxxx...
Successfully applied the patch.
...
As a root user, execute the following script(s):
1. /u01/app/oraInventory/orainstRoot.sh
2. /u01/app/oracle/product/19.0.0/dbhome_1/root.sh
Successfully Setup Software.
Run root scripts
/u01/app/oraInventory/orainstRoot.sh # only on the first Oracle install on this server /u01/app/oracle/product/19.0.0/dbhome_1/root.sh
Create the listener
DBCA does not create a listener. Create the default one (LISTENER, TCP 1521) first, so the new database registers with it immediately:
netca -silent -responseFile $ORACLE_HOME/assistants/netca/netca.rsp lsnrctl status
lsnrctl status shows LISTENER on port 1521.Create the database
A container database with one PDB: the non-CDB architecture is deprecated in 19c and desupported from 21c, so new databases should be CDBs.
dbca -silent -createDatabase \ -templateName General_Purpose.dbc \ -gdbName TESTCDB -sid TESTCDB \ -createAsContainerDatabase true -numberOfPDBs 1 -pdbName TESTPDB \ -characterSet AL32UTF8 -nationalCharacterSet AL16UTF16 \ -databaseType MULTIPURPOSE \ -memoryMgmtType AUTO_SGA -totalMemory 4096 \ -storageType FS -datafileDestination /u02/oradata -useOMF true \ -redoLogFileSize 1024 \ -enableArchive true \ -recoveryAreaDestination /u03/fra -recoveryAreaSize 20480 \ -emConfiguration NONE -sampleSchema false
Leave the passwords out: in silent mode DBCA then prompts for SYS, SYSTEM and the PDB admin password, so they never appear in shell history or ps output.
| Choice in this command | Why |
|---|---|
| No passwords on the command line | Typed passwords end up in shell history and process lists |
-createAsContainerDatabase true + PDB | Non-CDB is deprecated in 19c |
-redoLogFileSize 1024 (not 50 MB) | 50 MB logs switch constantly under any real load; aim for a few switches per hour |
-memoryMgmtType AUTO_SGA | Automatic SGA management; set -totalMemory to suit the server |
No -ignorePreReqs | Prerequisites should pass, not be skipped |
Verify & finish the patch
The binaries now carry the RU. Confirm that the dictionary does too. DBCA templates do not always include the latest SQL changes, so check every time:
$ORACLE_HOME/OPatch/opatch lspatches
SELECT banner_full FROM v$version; SELECT con_id, patch_id, action, status, description FROM cdb_registry_sqlpatch ORDER BY con_id, action_time; SHOW PDBS
If the RU is missing for any container, or shows anything other than SUCCESS, finish it:
cd $ORACLE_HOME/OPatch ./datapatch -verbose sqlplus / as sysdba @?/rdbms/admin/utlrp.sql
opatch lspatches and cdb_registry_sqlpatch show the same RU, with status SUCCESS in CDB$ROOT and the PDB, and no invalid objects.Autostart
Make the database and listener start with the server. Set the flag in /etc/oratab to Y:
TESTCDB:/u01/app/oracle/product/19.0.0/dbhome_1:Y
[Unit] Description=Oracle Database 19c (TESTCDB) After=network.target [Service] Type=forking User=oracle Group=oinstall Environment=ORACLE_HOME=/u01/app/oracle/product/19.0.0/dbhome_1 ExecStart=/u01/app/oracle/product/19.0.0/dbhome_1/bin/dbstart /u01/app/oracle/product/19.0.0/dbhome_1 ExecStop=/u01/app/oracle/product/19.0.0/dbhome_1/bin/dbshut /u01/app/oracle/product/19.0.0/dbhome_1 RemainAfterExit=yes TimeoutSec=600 [Install] WantedBy=multi-user.target
systemctl daemon-reload systemctl enable oracle-db # the PDB opens automatically after a restart once its state is saved:
ALTER PLUGGABLE DATABASE TESTPDB SAVE STATE;
Troubleshooting
| Message | Cause | Fix |
|---|---|---|
| INS-08101 / OS not supported during prechecks | 19.3 base installer on OL8/OL9 | Install with -applyRU (recent RU); on OL8, CV_ASSUME_DISTID=OL7 |
| OPatch version error during -applyRU | Old OPatch inside the new home | Replace $ORACLE_HOME/OPatch with the latest (Step 4) |
| INS-32047 inventory not empty | Another product in the same inventory | Warning only; continue |
| DBCA: listener not found / not registered | No listener when DBCA ran | Create it with netca (Step 9), then ALTER SYSTEM REGISTER; |
| RU missing in cdb_registry_sqlpatch | SQL part of the RU not applied | datapatch -verbose, then utlrp.sql |
| PDB MOUNTED after reboot | PDB state not saved | ALTER PLUGGABLE DATABASE TESTPDB OPEN; … SAVE STATE; |
Summary
Preinstall RPM → OFA directories → unzip the image → swap in the latest OPatch → runInstaller -applyRU → root.sh → netca → DBCA (CDB) → confirm datapatch → autostart. Script these twelve steps once, and every new 19c server comes out identical, fully patched, and ready for production checks.
What do you add to your own 19c build scripts? Share it in the comments.
References
- ORACLE-BASE: Apply a Release Update to a New Oracle Home
- ORACLE-BASE: DBCA Silent Mode
- Pythian: Run datapatch -prereq after creating a database
Tamilselvan Perumal · Oracle ACE Apprentice · Lead Product Engineer & Senior DBA

