暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

sqlplus执行错误的问题探究

1379

今天碰到个很诡异的问题,在装了Oracle Clinet的机器,不同路径下执行指令sqlplus,回显不同。

Oracle Client路径是/opt/app/oracle/instantclient_11_2,包含如下内容,

bash_profile相关配置,

    export ORACLE_HOME=/opt/app/oracle/instantclient_11_2
    export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ORACLE_HOME
    export TNS_ADMIN=$ORACLE_HOME
    export CLASSPATH=$ORACLE_HOME/ojdbc6.jar:./
    export NLS_LANG="AMERICAN_AMERICA.ZHS16GBK"
    export PATH=$PATH:$HOME/.local/bin:$HOME/bin:$SELF_ORACLE_HOME

    如果在$ORACLE_HOME,执行sqlplus,提示错误,再次执行,会出core,

      [test@localhost instantclient_11_2]$ cd opt/app/oracle/instantclient_11_2
      [test@localhost instantclient_11_2]$ sqlplus
      Error 6 initializing SQL*Plus
      SP2-0667: Message file sp1<lang>.msb not found
      SP2-0750: You may need to set ORACLE_HOME to your Oracle software directory

      如果在其他路径(非$ORACLE_HOME),执行sqlplus,回显正常,

        [test@localhost instantclient_11_2]$ sqlplus
        SQL*Plus: Release 11.2.0.4.0 Production on Wed Jul 22 17:48:07 2020
        Copyright (c) 1982, 2013, Oracle. All rights reserved.
        Enter user-name:

        这是为什么?

        通过strace发现了其中一些区别,sqlplus执行异常的strace片段,

          [test@localhost instantclient_11_2]$ strace sqlplus
          execve("/opt/app/oracle/instantclient_11_2/sqlplus", ["sqlplus"], [/* 29 vars */]) = 0
          brk(NULL) = 0x1b20000
          mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f9cb847c000
          access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
          open("tls/x86_64/libsqlplus.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
          open("tls/libsqlplus.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
          open("x86_64/libsqlplus.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
          open("libsqlplus.so", O_RDONLY|O_CLOEXEC) = 3
          read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0@\370\1\0\0\0\0\0"..., 832) = 832
          fstat(3, {st_mode=S_IFREG|0555, st_size=1469542, ...}) = 0
          getcwd("/opt/app/oracle/instantclient_11_2"128) = 54

          sqlplus执行正常的strace片段,

            [test@localhost instantclient_11_2]$ strace sqlplus
            execve("/opt/app/oracle/instantclient_11_2/sqlplus", ["sqlplus"], [/* 28 vars */]) = 0
            brk(NULL) = 0x16ec000
            mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fcd72b26000
            access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
            open("tls/x86_64/libsqlplus.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
            open("tls/libsqlplus.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
            open("x86_64/libsqlplus.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
            open("libsqlplus.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
            open("/opt/app/oracle/instantclient_11_2/tls/x86_64/libsqlplus.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
            stat("/opt/app/oracle/instantclient_11_2/tls/x86_64", 0x7fff93de3060) = -1 ENOENT (No such file or directory)
            open("/opt/app/oracle/instantclient_11_2/tls/libsqlplus.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
            stat("/opt/app/oracle/instantclient_11_2/tls", 0x7fff93de3060) = -1 ENOENT (No such file or directory)
            open("/opt/app/oracle/instantclient_11_2/x86_64/libsqlplus.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
            stat("/opt/app/oracle/instantclient_11_2/x86_64", 0x7fff93de3060) = -1 ENOENT (No such file or directory)
            open("/opt/app/oracle/instantclient_11_2/libsqlplus.so", O_RDONLY|O_CLOEXEC) = 3
            read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0@\370\1\0\0\0\0\0"..., 832) = 832
            fstat(3, {st_mode=S_IFREG|0555, st_size=1469542, ...}) = 0
            mmap(NULL, 1985056, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fcd72941000
            mprotect(0x7fcd72a17000, 1048576, PROT_NONE) = 0
            mmap(0x7fcd72b17000, 57344, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0xd6000) = 0x7fcd72b17000
            mmap(0x7fcd72b25000, 2592, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fcd72b25000
            close(3) = 0

            对比一下,可以看到,sqlplus执行异常的strace,打开libsqlplus.so成功,

              open("libsqlplus.so", O_RDONLY|O_CLOEXEC) = 3

              sqlplus执行正常的strace,打开libsqlplus.so失败,然后打开了带路径的,

                open("libsqlplus.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
                ...
                open("/opt/app/oracle/instantclient_11_2/libsqlplus.so", O_RDONLY|O_CLOEXEC) = 3

                如果说是解决,在LD_LIBRARY_PATH中开始处增加".",就是当前路径,此时无论在不在$ORACLE_HOME,sqlplus都可以正常执行,

                  export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH:$ORACLE_HOME

                  但是,原因是什么?

                  众所周知,LD_LIBRARY_PATH是Linux环境变量名,该环境变量主要用于指定查找共享库(动态链接库,例如此处的libsqlplus.so)时除了默认路径之外的其他路径。

                  当执行函数动态链接.so时,如果此文件不在缺省目录下/lib和/usr/lib,那么就需要指定环境变量LD_LIBRARY_PATH,有时候我们安装的软件,因为没root权限,不会放到这些系统路径下,因此要改LD_LIBRARY_PATH,指定查找的路径。因此,运行时动态库的搜索路径就需要先后顺序,1. 编译目标代码时指定的动态库搜索路径。2. 环境变量LD_LIBRARY_PATH指定的动态库搜索路径。3 .配置文件/etc/ld.so.conf中指定的动态库搜索路径。4. 默认的动态库搜索路径/lib和/usr/lib。

                  再回到这个问题,同样在$ORACLE_HOME路径下,执行sqlplus,strace的回显还是一样,但此时执行成功,说明sqlplus的执行路径是没问题的,关键还是LD_LIBRARY_PATH将"."当前路径加入了其中,

                    [test@localhost instantclient_11_2]$ strace sqlplus
                    execve("./sqlplus", ["sqlplus"], [/* 28 vars */]) = 0
                    brk(0) = 0x22c0000
                    mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f30b4903000
                    access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
                    open("./tls/x86_64/libsqlplus.so", O_RDONLY) = -1 ENOENT (No such file or directory)
                    open("./tls/libsqlplus.so", O_RDONLY) = -1 ENOENT (No such file or directory)
                    open("./x86_64/libsqlplus.so", O_RDONLY) = -1 ENOENT (No such file or directory)
                    open("./libsqlplus.so", O_RDONLY) = 3
                    read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0@\370\1\0\0\0\0\0"..., 832) = 832
                    fstat(3, {st_mode=S_IFREG|0555, st_size=1469542, ...}) = 0
                    getcwd("/opt/app/oracle/instantclient_11_2"128) = 58

                    对这个问题原因,还是有些含糊,这种解释,有些牵强,

                    1.不在$ORACLE_HOME执行,当前路径没libsqlplus.so,因此会到LD_LIBRARY_PATH定义的$ORACLE_HOME中找到带全路径的libsqlplus.so。

                    2.在$ORACLE_HOME执行,当前路径存在libsqlplus.so,但是LD_LIBRARY_PATH没定义"."当前路径,加载失败,当加入"."定义后,执行成功。

                    这个应该不是一个难题,还是考察的对环境变量的理解和运用,因此,还是希望各位路过的朋友、大神,能指点一二,找到合理的解释,在此谢过。

                    近期的热文:

                    如何查看JVM运行的堆内存情况

                    Centos能不能替换RHEL?

                    Linux下如何快速删除大量碎小的文件?

                    YNWA,同样是我们普通人的鞭策

                    海底的下面究竟有什么?

                    几种去重的SQL写法

                    打造国产技术产品的必要性

                    SQL查询总是先执行SELECT语句么?

                    Oracle删除字段的方式和风险,你都了解么?

                    登录缓慢的诡异问题

                    Linux下的^M困惑

                    Oracle相关提问的智慧技巧

                    很久以前的一篇对初学Oracle建议的文章

                    PLSQL Developer几个可能的隐患

                    从70万字SRE神作提炼出的7千字精华文章

                    从数据误删到全量恢复的惊险记录

                    OpenJDK和Oracle JDK有什么区别和联系?

                    公众号600篇文章分类和索引

                    文章转载自bisal的个人杂货铺,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                    评论