Introdução
Ao longo dos últimos tempos realizando uma quantidade cada vez mais de atualizações usando a abordagem Out-Of-Place, aliada a uma demanda crescente por automação para mitigação de erros no ambiente, comecei a trabalhar na ideia de ter um script pra servir como um auxiliar de configuração do Listener durante as janelas de manutenção.
O principal motivador para isso foi o fato de ter que lidar com alguns ambientes que eventualmente tinham registro estático no arquivo listener.ora que ficavam obsoletos a cada atualização. Mesmo no ambiente com automação do FPP, depois de algumas experiências observei que a ferramenta também não atualizava o conteúdo do arquivo listener.ora como eu esperava que fizesse, além de outro detalhe que até a versão atual (21c), a ferramenta não move o Listener quando o ambiente é do tipo Standalone (apenas RDBMS, sem GRID).
Com isso, eu precisei criar o script oop_listener_helper.sh para atender dois requisitos:
- Ambiente Standalone: Mover o Listener do DB home antigo para o novo, e atualizar os registros estáticos
- Ambiente com GRID: Atualizar os registros estáticos e fazer reload do listener.
Esse ajuste do registro estático é importante porque se você remove um DB Home antigo que ainda está sendo usado em algum serviço registrado estaticamente, a próxima inicializacão do Listener irá falhar com um erro similar a esse:
TNS-01201: Listener cannot find executable /u01/app/oracle/product/19.0.0/DB1923/bin/oracle for SID CDBTSSL
O Script
Você pode obter o código do script oop_listener_helper.sh aqui no repositório do blog.
Esse é um script simples e honesto, ele não irá resolver sua vida ou fazer algo expecional, mas cumpre essas duas necessidades que comentei na introdução e conta com os seguintes parâmetros para usar em cada execução:
Parâmetros
| Opção | Uso |
|---|---|
| -sourcehome | Indica o caminho do Oracle Home antigo |
| -desthome | Indica o caminho do Oracle Home novo |
| -listener_home | Indica o caminho atual do OH onde o Listener está executando. |
| -move | Move o LISTENER do OH antigo para o OH novo. |
| -copy | Copia os arquivos network/admin/*.ora do OH antigo para o OH novo. |
| -update | Faz um replace no arquivo listener.ora trocando o OH antigo pelo OH novo em cada registro estático. |
| -reload | Executa um reload no Listener (lsnrctl reload) |
Exemplos em Oracle Standalone
Copy & Move
Exemplo de como executar o script em um ambiente Standalone (sem Grid), antes de reiniciar a instância:
./oop_listener_helper.sh \ -sourcehome /u01/app/oracle/product/19.22.0.0/dbhome_1 \ -desthome /u01/app/oracle/product/19.25.0.0/dbhome_1 \ -copy -move
Este comando irá copiar os arquivos de configuração para o OH de destino, realizar o “lsnrctl stop” na origem e “lsnrctl start” no destino.
Exemplo da situação original, o Listener está executando no OH 19.22:
[oracle@lab06 ~]$ ps -ef | grep tnslsnr
oracle 21096 1 0 14:52 ? 00:00:00 /u01/app/oracle/product/19.22.0.0/dbhome_1/bin/tnslsnr listener -inherit
E o arquivo listener.ora tem uma entrada estática para o SID “DB06A” apontando para o OH 19.22:
[oracle@lab06 ~]$ cat /u01/app/oracle/product/19.22.0.0/dbhome_1/network/admin/listener.ora
SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(SID_NAME = DB06A)
(ORACLE_HOME = "/u01/app/oracle/product/19.22.0.0/dbhome_1")
(GLOBAL_DBNAME=DB06A_test)
(ENVS="TNS_ADMIN=/u01/app/oracle/product/19.22.0.0/dbhome_1/network/admin")
)
)
Após executar o script, o Listener deve estar executando no novo Oracle Home (19.25):
[oracle@lab06 ~]$ ps -ef | grep tnslsnr
oracle 21241 1 0 14:55 ? 00:00:00 /u01/app/oracle/product/19.25.0.0/dbhome_1/bin/tnslsnr listener -inherit
Mas o conteúdo do arquivo listener.ora permanece inalterado, porque não usamos a opção -update:
SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(SID_NAME = DB06A)
(ORACLE_HOME = "/u01/app/oracle/product/19.22.0.0/dbhome_1")
(GLOBAL_DBNAME=DB06A_test)
(ENVS="TNS_ADMIN=/u01/app/oracle/product/19.22.0.0/dbhome_1/network/admin")
)
)
Copy & Move & Update
Para mover o Listener para o novo Oracle Home e atualizar as entradas de registro estático:
./oop_listener_helper.sh \ -sourcehome /u01/app/oracle/product/19.22.0.0/dbhome_1 \ -desthome /u01/app/oracle/product/19.25.0.0/dbhome_1 \ -copy -update -move
Com a opção -update, além de o Listener ser movido para o novo OH, o arquivo listener.ora também será atualizado para apontar para o novo OH.
Como o arquivo listener.ora deve ficar depois:
SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(SID_NAME = DB06A)
(ORACLE_HOME = "/u01/app/oracle/product/19.25.0.0/dbhome_1")
(GLOBAL_DBNAME=DB06A_test)
(ENVS="TNS_ADMIN=/u01/app/oracle/product/19.25.0.0/dbhome_1/network/admin")
)
)
Exemplo com Grid Infrastructure
Quando o OOP é executado em ambiente com Grid, seja Single ou Cluster, a parte de mover o Listener para o novo GI Home é realizada pelo próprio processo de OOP. Neste caso, o que precisamos fazer após o restart dos serviços é apenas atualizar os registros estáticos e forçar um reload do Listener.
Exemplo, neste outro servidor, o Listener e a instância já foram movidos para o novo Oracle Home com RU 19.25:
[grid@lab03 ~]$ ps -ef | grep tnslsnr
grid 52164 1 0 16:11 ? 00:00:03 /u01/app/19.0.0/GI1925/bin/tnslsnr LISTENER -no_crs_notify -inherit
[grid@lab03 ~]$ srvctl config database -d CDBTSSL | grep home
Oracle home: /u01/app/oracle/product/19.0.0/DB1925
Mas o registro estático continua apontando para o OH antigo no arquivo listener.ora:
SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(SID_NAME = CDBTSSL)
(ORACLE_HOME = "/u01/app/oracle/product/19.0.0/DB1924")
(GLOBAL_DBNAME=CDBTSSL_test)
(ENVS="TNS_ADMIN=/u01/app/oracle/product/19.0.0/DB1924/network/admin")
)
)
Note que o script deve ser sempre executado pelo usuário que é owner do OH onde o Listener executa. Exemplo, em um ambiente Standalone, você provavelmente executará com o usuário “oracle”, enquanto em um ambiente com Grid Infrastructure, provavelmente será com o usuário “grid”.
Update & Reload
Exemplo de como executar o script neste cenário, onde o Listener já está executando no novo GI Home:
./oop_listener_helper.sh \ -sourcehome /u01/app/oracle/product/19.0.0/DB1924 \ -desthome /u01/app/oracle/product/19.0.0/DB1925 \ -listener_home /u01/app/19.0.0/GI1925 \ -update -reload
Observe que estou incluindo o parâmetro -listener_home passando o caminho do GI HOME (Porque o Listener roda no GRID), e ao invés de usar a opção -move, estou usando a opção -reload.
A saída do comando deve ser similar a essa:
Backup created at /u01/app/19.0.0/GI1925/network/admin/TNS_BACKUP_20241202_18-15-41.zip
Updating file listener.ora in /u01/app/19.0.0/GI1925/network/admin with OLD_HOME=/u01/app/oracle/product/19.0.0/DB1924 and NEW_HOME=/u01/app/oracle/product/19.0.0/DB1925
Reloading LISTENER
LSNRCTL for Linux: Version 19.0.0.0.0 - Production on 02-DEC-2024 18:15:41
Copyright (c) 1991, 2024, Oracle. All rights reserved.
Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=lab03.dibiei.com)(PORT=1521)))
The command completed successfully
E o resultado esperado é ter a entrada do registro estático atualizado com o novo DB Home:
[grid@lab03 ~]$ cat /u01/app/19.0.0/GI1925/network/admin/listener.ora
...
SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(SID_NAME = CDBTSSL)
(ORACLE_HOME = "/u01/app/oracle/product/19.0.0/DB1925")
(GLOBAL_DBNAME=CDBTSSL_test)
(ENVS="TNS_ADMIN=/u01/app/oracle/product/19.0.0/DB1925/network/admin")
)
)
Uso em Oracle RAC
Para ambientes com cluster, o modo de uso é mesmo do exemplo demonstrado com Grid infrastructure single, o que muda é que o script precisa ser executado em cada node do cluster.
Uso com Autoupgrade “One Button Patching”
Se você usa Autoupgrade em ambientes sem Grid Infrastructure, pode considerar os cenários abaixo.
A ferramenta da Oracle Autoupgrade em sua versão mais recente pode ser usada para aplicar patch Out-Of-Place em DB Homes Single. Até a versão que eu testei mais recentemente (24.8.241119), a ferramenta copia o arquivo listener.ora para o novo DB Home, mas não reinicia o Listener automaticamente (não é uma falha, é proposital).
Além de copiar o arquivo, a ferramenta também atualiza o conteúdo do arquivo substituindo o caminho do DB Home antigo pelo novo quando tem registro de serviço estático.
Autoupgrade Patching 1-Step: -mode deploy
Se você usar a opção de patch em uma única etapa, executando apenas a opção “deploy” e deixando o Autoupgrade fazer tudo de uma vez, você só precisa usar a opção -move do script oop_listener_helper para reiniciar o Listener no novo Oracle Home, logo após o término do JOB do Autoupgrade.
Exemplo:
./oop_listener_helper.sh \ -sourcehome /u01/app/oracle/product/19.22.0.0/dbhome_1 \ -desthome /u01/app/oracle/product/19.25.0.0/dbhome_1 \ -move
A ordem dos comandos ficaria assim:
java -jar autoupgrade.jar -patch ... -mode deploy
./oop_listener_helper.sh ... -move
Autoupgrade Patching 2-Step: create_home & deploy
Se você optar por executar o Autoupgrade Patching em duas etapas, criando o novo Oracle Home previamente antes do deploy, então você pode rodar o script oop_listener_helper entre o JOB de “create_home” e “deploy“. Neste caso, precisa usar todas as opções do script.
Exemplo:
./oop_listener_helper.sh \ -sourcehome /u01/app/oracle/product/19.22.0.0/dbhome_1 \ -desthome /u01/app/oracle/product/19.25.0.0/dbhome_1 \ -copy -update -move
A ordem dos comandos ficariam assim:
java -jar autoupgrade.jar -patch ... -mode create_home
./oop_listener_helper.sh ... -copy -update -move
java -jar autoupgrade.jar -patch ... -mode deploy
Uso com Fleet Patching and Provisioning (FPP)
O FPP até a versão 19c também não move o Listener quando o ambiente não tem Grid, e também não atualiza os registros estáticos do Listener que roda no GI Home. Eu estou ajustando uma versão adaptada do script que pode ser executada automaticamente pelo FPP como uma UserAction e pretendo escrever um post sobre isso posteriormente.
Rollback
Para fazer rollback das alterações realizada pelo script, a ideia é a mesma do Out-Of-Place patching em si: Basta executar novamente, só que invertendo o caminho do Oracle Home usado como origem e destino. Uma dica específica sobre rollback é que você não precisa da opção -copy, uma vez que os arquivos já devem existir no OH original.
Conclusão
Conforme demonstrado nos exemplos acima, você pode usar o script oop_listener_helper.sh como um auxiliar no seu processo de Out-Of-Place patching. Mesmo que pareça algo simples quando se está acostumado a fazer isso toda semana, uma das principais vantagens de usar o script é que você mitiga a possibilidade de erros no domingo ás 02h da manhã, além de ser mais seguro repassar a atividade a atividade para um profissional menos experiente no processo.
Por fim, o script também pode ser usado como uma ação de Pós-Patch dentro de alguma automação customizada, ou com outras ferramentas que ainda não lida com a atualização do conteúdo do listener.ora, como é o caso do FPP até a versão 19c.
Pingback: AutoUpgrade Patching: Como Automatizar o Restart do Listener no Novo Oracle Home (Standalone Server) – Blog do Dibiei