AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 50965
Accepted
vegatripy
vegatripy
Asked: 2013-10-04 09:16:00 +0800 CST2013-10-04 09:16:00 +0800 CST 2013-10-04 09:16:00 +0800 CST

Oracle 的 UTL_FILE 在本地连接或通过侦听器连接时具有不同的行为

  • 772

我们有一个使用 UTL_FILE 创建 CSV 文件的过程。(env 是 Oracle 11.2.0.1 和 RHEL 6.4)到目前为止,我们将该 CSV 文件存储到系统oracle(oracle 所有者)用户主目录 (/home/oracle/csv/) 中。它工作正常,但现在我们需要将 CSV 文件存储到不同的系统用户主目录(例如reports系统用户主目录 (/home/reports/csv/))

因此,我们将oracle用户添加到该组reports作为其次要组,然后将reports主页权限更改为他和他的所有组都可以访问。

# 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

有了这个,登录到系统,oracle我可以写入,读取和执行文件到reports's home。

# 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

现在,据我所知(甲骨文的文档说),这应该有效,但它没有......根本没有。 如果我用 sqlplus 在本地连接,它可以工作。但是如果我从远程机器或通过监听器连接,我不会!

我将向您展示: 与 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

现在,让我们再次尝试通过侦听器连接 让我们看看我的 tnsnames 指向哪里:

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

现在,如果我将reports's home 权限更改为所有人都可以访问,则通过侦听器连接的 UTL_FILE 过程可以正常工作!

# 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

???

我不明白为什么会有这种行为。正如甲骨文的文档所说:

( http://docs.oracle.com/cd/B28359_01/appdev.111/b28419/u_file.htm )

在 UNIX 系统上,由 FOPEN 函数创建的文件的所有者是运行实例的影子进程的所有者

影子进程的所有者在两种方法中都相同(即“oracle”系统用户),所以,.. 为什么会这样?

有人有线索吗?我错过了什么吗?

oracle oracle-11g
  • 2 2 个回答
  • 3823 Views

2 个回答

  • Voted
  1. miracle173
    2014-03-04T14:17:15+08:002014-03-04T14:17:15+08:00

    这是 Unix 系统上的预期行为。进程的有效用户 ID 允许读/写文件或其有效的主要或有效的辅助组 ID 允许读/写文件

    如果您登录到 unix 系统,则有效用户 id、有效组 id 和有效辅助组 id 是为您在该系统上的登录用户定义的 id(在 /etc/passwd 或任何地方)。如果一个unix进程创建了一个新进程,那么新进程会从创建进程继承这个id。

    Oracle 影子进程是对应于 oracle 会话的 unix 进程。如果您使用网络连接登录数据库,则此影子进程由侦听器进程创建。如果您向 oracle unix 用户添加新的辅助组 ID,这不会更改正在运行的侦听器进程的有效 ID,因此所有新创建的进程都具有与添加新辅助之前创建的进程相同的有效用户/组 ID团体。

    但是,如果您在向 oracle 用户添加新的辅助组 id 后登录系统,您的登录会话将有这个额外的有效辅助组 id,如果您停止并启动侦听器进程,它也会有额外的有效辅助组 id . 新的侦听器进程创建的影子进程也是如此。

    如果侦听器进程在添加新的辅助组 id 后被另一个进程停止,但在添加新的辅助组 id 后该其他进程没有重新启动,则侦听器不会将新的辅助组 id 作为有效的辅助组 id,即使他被重新启动,因为启动侦听器进程的进程没有新的辅助 id 作为有效的辅助 id。如果您通过某个集群进程重新启动侦听器进程,则可能会发生这种情况。在这种情况下,必须先重新启动此集群进程,然后才能重新启动侦听器进程,以使新添加的辅助组 id 生效。

    如果您使用 sqlplus 进行本地连接,则影子进程由 sqlplus 生成,而不是由侦听器进程生成。但是 sqlplus 进程具有由您的登录会话继承的有效用户/组 ID。那么您在添加新的辅助组后是否登录,那么影子进程将具有此辅助组 ID。如果在将辅助组添加到 oracle 用户之前已经建立了登录,那么您的 unix 会话的所有新本地 sqlplus 连接(= 影子进程)也不会将此额外的辅助组 ID 作为有效的辅助组 ID。

    • 2
  2. Best Answer
    vegatripy
    2013-10-05T01:41:50+08:002013-10-05T01:41:50+08:00

    正如 Colin 't Hart 和 Phil 在评论中建议的那样,我不得不重新启动监听器。这就是问题所在!

    通过监听器的新数据库连接继承了监听器启动时使用的环境变量、组等,因为新的 Oracle 进程是从监听器派生的。组成员在 Linux 上的进程启动时被缓存

    非常感谢,我整天都被困在这个问题上。

    问候

    更新

    最近,我在使用调度程序执行的过程中遇到了类似的情况。在这种情况下,影子进程由作业协调进程 (CJQ0) 生成。在这里,您将需要重新启动整个数据库(您可以杀死 CJQ0,但随后它由进程监视器生成,有同样的问题)。

    作为一种解决方法,您可以使用 linux 访问控制列表setfacl。有了它,该过程无需重新启动即可重新加载组成员资格。

    • 0

相关问题

  • Oracle 中的数据库备份 - 导出数据库还是使用其他工具?

  • ORDER BY 使用文本列的自定义优先级

  • 舒服的sqlplus界面?[关闭]

  • 如何在数据库中找到最新的 SQL 语句?

  • 如何使用正则表达式查询名称?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    授予用户对所有表的访问权限

    • 5 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    pedrosanta 使用 psql 列出数据库权限 2011-08-04 11:01:21 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve