Temos um procedimento que cria um arquivo CSV com UTL_FILE. (env é Oracle 11.2.0.1 e RHEL 6.4) Até agora, estávamos armazenando esse arquivo CSV na oracle
home do usuário do sistema (o proprietário do oracle) (/home/oracle/csv/). Funciona bem, mas agora somos obrigados a armazenar o arquivo CSV em uma página inicial do usuário do sistema diferente (por exemplo , página reports
inicial do usuário do sistema (/home/reports/csv/))
Portanto, adicionamos o oracle
usuário ao grupo reports
como seu grupo secundário e, em seguida, alteramos reports
as permissões iniciais para que ele e todo o grupo possam acessá-lo.
# id oracle
uid=500(oracle) gid=500(oracle) grupos=500(oracle),502(reports)
# id reports
uid=502(reports) gid=502(reports) grupos=502(reports)
# chmod 770 /home/reports
# ls -la /home/reports/
total 52
drwxrwx--- 8 reports reports 4096 oct 3 12:58 .
drwxr-xr-x. 5 root root 4096 oct 2 11:05 ..
drwxrwxrwx 2 reports reports 4096 oct 3 12:59 csv
Com isso, logando no sistema, oracle
posso escrever, ler e executar arquivos na reports
casa do.
# su - oracle
oracle ~$ touch /home/reports/csv/test.txt
oracle ~$ ls -la /home/reports/csv/test.txt
total 8
-rw-rw-r-- 1 oracle oracle 0 oct 3 17:51 test.txt
E agora, até onde eu sei (e a documentação da Oracle diz), isso deveria funcionar, mas não .. de jeito nenhum. Se eu conectar localmente com o sqlplus, funciona. Mas se eu conectar de uma máquina remota ou através do ouvinte, não!
Vou te mostrar: Conexão local com sqlplus:
oracle ~$ export ORACLE_SID=MYDB
oracle ~$ sqlplus -S informes
Introduzca la contraseña:
select a.directory_name,
a.directory_path,
b.grantee,
b.privilege
from all_directories a,
all_tab_privs b
where a.directory_name = b.table_name
and DIRECTORY_NAME='CSVFOLDER';
DIRECTORY_NAME DIRECTORY_PATH GRANTEE PRIVILEGE
------------------------------ -------------------- --------- ---------
CSVFOLDER /home/reports/csv INFORMES READ
CSVFOLDER /home/reports/csv INFORMES WRITE
show user
USER es "INFORMES"
declare
output_fich utl_file.file_type;
begin
output_fich := utl_file.fopen('CSVFOLDER','testfile.csv','W');
utl_file.put_line (output_fich, 'test line');
utl_file.fclose(output_fich);
end;
/
Procedimiento PL/SQL terminado correctamente.
host ls -la /home/reports/csv/testfile.csv
-rw-rw-r-- 1 oracle oracle 10 oct 3 18:20 /home/informesestados/tmp/testfile.csv
host rm /home/reports/csv/testfile.csv
Agora, vamos tentar novamente conectando através do ouvinte Vamos ver para onde meu tnsnames está apontando:
oracle ~$ cat $ORACLE_HOME/network/admin/tnsnames.ora | grep MYDB
MYDB = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = FR-BD1-tmp)(PORT = 1522))) (CONNECT_DATA = (SERVICE_NAME = MYDB)))
oracle ~$ ping FR-BD1-tmp
PING fr-bd1-tmp (192.168.78.3) 56(84) bytes of data.
64 bytes from fr-bd1-tmp (192.168.78.3): icmp_seq=1 ttl=64 time=0.047 ms
64 bytes from fr-bd1-tmp (192.168.78.3): icmp_seq=2 ttl=64 time=0.025 ms
^C
--- fr-bd1-tmp ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1386ms
rtt min/avg/max/mdev = 0.025/0.036/0.047/0.011 ms
oracle ~$ /sbin/ifconfig | grep "inet addr"
inet addr:192.168.78.3 Bcast:192.168.78.255 Mask:255.255.255.0
oracle ~$ lsnrctl services LISTENER_MYBD
LSNRCTL for Linux: Version 11.2.0.1.0 - Production on 03-OCT-2013 18:33:04
Copyright (c) 1991, 2009, Oracle. All rights reserved.
Conectándose a (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=fr-bd1-tmp)(PORT=1522)))
Resumen de Servicios...
El servicio "mydb" tiene 1 instancia(s).
La instancia "mydb", con estado READY, tiene 1 manejador(es) para este servicio...
Manejador(es):
"DEDICATED" establecido:45 rechazado:0
LOCAL SERVER
El servicio "mydb_node1" tiene 1 instancia(s).
La instancia "mydb", con estado READY, tiene 1 manejador(es) para este servicio...
Manejador(es):
"DEDICATED" establecido:3 rechazado:0 estado:ready
LOCAL SERVER
El comando ha terminado correctamente
oracle ~$ sqlplus -S informes@mydb
Introduzca la contraseña:
select a.directory_name,
a.directory_path,
b.grantee,
b.privilege
from all_directories a,
all_tab_privs b
where a.directory_name = b.table_name
and DIRECTORY_NAME='CSVFOLDER';
DIRECTORY_NAME DIRECTORY_PATH GRANTEE PRIVILEGE
------------------------------ -------------------- --------- ---------
CSVFOLDER /home/reports/csv INFORMES READ
CSVFOLDER /home/reports/csv INFORMES WRITE
show user
USER es "INFORMES"
declare
output_fich utl_file.file_type;
begin
output_fich := utl_file.fopen('INFORMES','testfile.csv','W');
utl_file.put_line (output_fich, 'test line');
utl_file.fclose(output_fich);
end;
/
declare
*
ERROR en línea 1:
ORA-29283: operación de archivo no válida
ORA-06512: en "SYS.UTL_FILE", línea 536
ORA-29283: operación de archivo no válida
ORA-06512: en línea 4
Agora, se eu alterar reports
as permissões iniciais do 's para serem acessíveis a todos, o procedimento UTL_FILE por meio da conexão do ouvinte funcionará!
# chmod 777 /home/reports
# ls -la /home/reports/
total 52
drwxrwxrwx 8 reports reports 4096 oct 3 12:58 .
drwxr-xr-x. 5 root root 4096 oct 2 11:05 ..
drwxrwxrwx 2 reports reports 4096 oct 3 12:59 csv
# su - oracle
oracle ~$ sqlplus -S informes@mydb
Introduzca la contraseña:
declare
output_fich utl_file.file_type;
begin
output_fich := utl_file.fopen('CSVFOLDER','testfile.csv','W');
utl_file.put_line (output_fich, 'test line');
utl_file.fclose(output_fich);
end;
/
Procedimiento PL/SQL terminado correctamente.
host ls -la /home/reports/csv/testfile.csv
-rw-rw-r-- 1 oracle oracle 10 oct 3 18:59 /home/informesestados/tmp/testfile.csv
???!!
Não entendo por que esse comportamento. Como diz a documentação da Oracle:
( http://docs.oracle.com/cd/B28359_01/appdev.111/b28419/u_file.htm )
Em sistemas UNIX, o proprietário de um arquivo criado pela função FOPEN é o proprietário do processo de sombra executando a instância
O proprietário do processo shadow é o mesmo em ambos os métodos (ou seja, usuário do sistema ''oracle''), então, por que isso?
Alguém tem uma pista? Estou esquecendo de algo?
Este é o comportamento esperado em um sistema unix. o ID de usuário efetivo de um processo permite ler/gravar um arquivo ou seus IDs de grupo primário efetivo ou secundário efetivo permitem ler/gravar os arquivos
Se você efetuar logon em um sistema unix, o ID de usuário efetivo, o ID de grupo efetivo e os IDs de grupo secundário efetivos são os IDs definidos para seu usuário de login neste sistema (em /etc/passwd ou em qualquer lugar). se um processo unix criar um novo processo, o novo processo herdará esses IDs do processo de criação.
O processo de sombra Oracle é o processo unix que corresponde a uma sessão oracle. Esse processo de sombra é criado pelo processo de escuta se você efetuar login no banco de dados usando uma conexão de rede. Se você adicionar um novo ID de grupo secundário ao usuário oracle unix, isso não altera os IDs efetivos do processo de escuta em execução e, portanto, todos os processos recém-criados têm os mesmos IDs de usuário/grupo efetivos que os processos criados antes da adição do novo secundário grupo.
Mas se você fizer login no sistema depois de adicionar o novo id de grupo secundário ao usuário oracle, sua sessão de login terá esse id de grupo secundário efetivo adicional e se você parar e iniciar o processo de escuta, ele também terá o id de grupo secundário efetivo adicional . O mesmo acontecerá com os processos sombra criados pelo novo processo ouvinte.
Se o processo do ouvinte for iniciado e interrompido por outro processo após adicionar o novo ID do grupo secundário, mas esse outro processo não for reiniciado após adicionar o novo ID do grupo secundário, o ouvinte não terá o novo ID do grupo secundário como ID efetivo do grupo secundário, mesmo se ele é reiniciado porque o processo que inicia o processo do ouvinte não tinha o novo id secundário como id secundário efetivo. Isso pode acontecer se você reiniciar o processo do ouvinte por algum processo de cluster. Nesse caso, esse processo de cluster deve ser reiniciado antes de reiniciar o processo do ouvinte para que o ID do grupo secundário recém-incluído entre em vigor.
Se você fizer uma conexão local usando sqlplus, o processo de sombra será gerado pelo sqlplus e não por um processo ouvinte. mas o processo sqlplus tem os IDs de usuário/grupo efetivos herdados por sua sessão de login. você está conectado depois de adicionar o novo grupo secundário, então o processo de sombra terá esse ID de grupo secundário. Se o seu login já foi estabelecido antes do grupo secundário ser adicionado ao usuário oracle, todas as novas conexões sqlplus locais (= processos de sombra) da sua sessão unix não terão esse id de grupo secundário adicional como id de grupo secundário efetivo.
Como Colin 't Hart e Phil sugeriram nos comentários, tive que reiniciar o ouvinte. Esse era o problema!
Muito obrigado, fiquei preso nisso o dia todo.
Cumprimentos
ATUALIZAR
Recentemente enfrentei uma situação semelhante com um procedimento executado com o Scheduler. Nesse caso, o processo de sombra é gerado pelo processo do coordenador de tarefas (CJQ0). Aqui você precisará reiniciar todo o banco de dados (você pode matar o CJQ0, mas ele é gerado pelo monitor de processo, tendo o mesmo problema).
Como solução alternativa, você pode usar listas de controle de acesso do Linux
setfacl
. Com ele, o processo não precisa ser reiniciado para recarregar a associação ao grupo.