配置 UnixODBC
夢之上關注IP屬地: 香港
0.2322020.12.09 13:23:10字數 1,202閱讀 5,447
麒麟&達夢適配系列:
1.麒麟服務器上安裝 DM8
2.配置 UnixODBC
3.beego-ORM 適配達夢
資源緊張的時候,服務器是大家共用的,上面部署了一堆服務。所以選用docker 進行 unix odbc 的編譯和適配。避免牽一發而動全身,影響他人使用。(我不會告訴你其實:是服務器 gcc 版本太低了,編譯報錯)
因為最終,我們是使用 golang 進行開發的。所以基于 golang1.14 鏡像來構建。
1 創建 Dockerfile
root@Kylin:/data/liutongtong011# cd /data/liutongtong011
root@Kylin:/data/liutongtong011# touch Dockerfile
Dockerfile 內容:
FROM golang:1.14RUN apt-get update && \apt-get install -y unixodbc-dev unixodbc && \go get github.com/alexbrainman/odbc
2 根據 Dockerfile build 鏡像
docker build - < Dockerfile -t liutongtong011
3 查看鏡像是否存在
docker images | grep liutongtong011
4 啟動容器
docker run -it liutongtong011
說明:執行完 docker run 自動就登錄到容器內了。如果想要再其他session進入容器,執行以下步驟:
5 查看容器 ID
docker ps | grep liutongtong
說明:第一列即為容器 ID
6 登錄容器
docker exec -it 017a0f7a3067 bash
容器啟動成功后,在容器內部進行 UnixODBC 的配置:
1 使用 odbcinst -j
命令查看 odbc的配置
root@Kylin:/go# odbcinst -j
unixODBC 2.3.6
DRIVERS............: /etc/odbcinst.ini
SYSTEM DATA SOURCES: /etc/odbc.ini
FILE DATA SOURCES..: /etc/ODBCDataSources
USER DATA SOURCES..: /root/.odbc.ini
SQLULEN Size.......: 8
SQLLEN Size........: 8
SQLSETPOSIROW Size.: 8
2 配置 odbc.ini
[DM8]
Description = DM ODBC DSN
Driver = DM8 ODBC DRIVER
SERVER = 172.0.0.1
UID = SYSDBA
PWD = SYSDBA
TCP_PORT = 5236
說明:為了減少出錯的可能,我就直接將 /root/.odbc.ini
和 /etc/odbc.ini
配置成一樣的了
3 配置 odbcinst.ini
[DM8 ODBC DRIVER]
Description = ODBC DRIVER FOR DM8
Driver = /opt/dmdbms/bin/libdodbc.so
Setup = /lib/libdmOdbcSetup.so
threading = 0
說明:
- 這里的 title
[DM8 ODBC DRIVER]
必須和 odbc.ini 中的 Driver 保持一致 - 這里的
/opt/dmdbms/bin/libdodbc.so
是達夢的 so,而非 UnixODBC 自帶的
4 使用 isql
登錄數據庫
root@Kylin:/go# isql -v DM8
+---------------------------------------+
| Connected! |
| |
| sql-statement |
| help [tablename] |
| quit |
| |
+---------------------------------------+
說明:-v
的作用是,一旦報錯,可以展示報錯詳情
5 執行任意 sql 測試
SQL> select * from v$version;
+---------------------------------------------------------------------------------+
| BANNER |
+---------------------------------------------------------------------------------+
| DM Database Server 64 V8|
| DB Version: 0x7000b |
+---------------------------------------------------------------------------------+
SQLRowCount returns 2
2 rows fetched
如果 isql
可以成功連接DB,并能執行測試語句,說明 UnixODBC 配置成功。
這里簡單介紹幾個Docker命令,熟悉Docker的同學可以跳過這一趴:
docker commit e9f39c7081e0 unixodbc001
說明:
- e9f39c7081e0: 正在運行的容器ID,可以使用
docker ps
查看 - unixodbc001:自定義的鏡像名稱
docker tag unixodbc001 registry.cn-beijing.aliyuncs.com/liutongtong/unixodbc001:V0.1
docker push registry.cn-beijing.aliyuncs.com/liutongtong/unixodbc001:V0.1
說明:像鏡像倉庫中提交該鏡像,以后用的時候,直接拉取即可。
現實往往是殘酷的,上面簡單的幾步中可能會遇到許多問題。
我把自己在安裝過程中踩的坑,報的錯及解決方案列在下面,供大家參考:
使用源碼編譯安裝UnixODBC:
起初在網上找了達夢大學的官方教程:http://www.dameng.com/teachers_view.aspx?TypeId=183&Id=891&FId=t26:183:26
按照里面的步驟進行源碼安裝。最先遇到的問題是:
=> configure 時報錯:cannot guess build type
./configure
UNAME_MACHINE = aarch64
UNAME_RELEASE = 4.4.131-20200704.kylin.server-generic
UNAME_SYSTEM = Linux
UNAME_VERSION = #kylin SMP Sat Jul 4 19:29:27 CST 2020
configure: error: cannot guess build type; you must specify one
解決辦法:./configure --build=arm
=> 無法編譯出 .so文件
即便增加enable-shared
也無法解決問題
./configure --build=arm --enable-shared
編譯出來的始終是 .a
和 .la
文件。
嘗試手動合成 .so
root@greatwall-os:/usr/local/lib# ar -x libodbcinst.a
root@greatwall-os:/usr/local/lib# gcc -shared *.o -o libodbcinst.so
報錯:
/usr/bin/ld: libltdlc_la-ltdl.o: relocation R_AARCH64_ADR_PREL_PG_HI21 against external symbol `__stack_chk_guard@@GLIBC_2.17' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: libltdlc_la-ltdl.o(.text+0x6e4): 無法解決 R_AARCH64_ADR_PREL_PG_HI21 重定向于符號 “__stack_chk_guard@@GLIBC_2.17” 有沖突
/usr/bin/ld: 最后的鏈結失敗: 錯誤的值
collect2: error: ld returned 1 exit status
解決辦法:清除現有 odbc,增加 configure 參數后重新安裝
make uninstall && make cleanCFLAGS="-fPIC" ./configure --build=arm
# 編譯出來還是 .a ,但是這回 .a 是可以合并成 .so 的ar -x /usr/local/lib/libodbc.a
gcc -shared *.o -o libodbc.so
=> could not determine kind of name for C.SQL_WLONGVAR
之前用的UnixODBC2.21版本過低,升級到2.3.2即可解決問題
=> isql 時報 file not found
[root@dameng-test001 dameng]# isql -v DM8 SYSDBA SYSDBA
[01000][unixODBC][Driver Manager]Can't open lib '/home/dmdba/dmdbms/bin/libdodbc.so' : file not found
使用 ls -l /home/dmdba/dmdbms/bin/libdodbc.so
命令可以看到文件存在,且權限為可訪問。
使用 ldd
命令查看依賴是否有問題:
[root@dameng-test001 dameng]# ldd /home/dmdba/dmdbms/bin/libdodbc.solinux-vdso.so.1 => (0x00007fff36943000)libdmdpi.so => not foundlibdmfldr.so => not foundlibrt.so.1 => /lib64/librt.so.1 (0x00007fbcec98a000)libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fbcec76e000)libdl.so.2 => /lib64/libdl.so.2 (0x00007fbcec56a000)libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007fbcec263000)libm.so.6 => /lib64/libm.so.6 (0x00007fbcebf61000)libc.so.6 => /lib64/libc.so.6 (0x00007fbcebb93000)libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007fbceb97d000)/lib64/ld-linux-x86-64.so.2 (0x00007fbcece44000)
發現是找不到以來的lib
進行全局查找:find / -name "libdmdpi.so"
發現實際上時存在的。路徑為:/home/dmdba/dmdbms/bin/
(這里路徑和之前不一致是因為,為了保證可行性,先在Linux上做了適配)
在 .bash_profile
中配置 LD_LIBRARY_PATH 變量:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/dmdba/dmdbms/bin/
=>[S1000][unixODBC]Encryption module failed to load
這是因為,在DM8中,加密模塊已不在libdodbc.so
中
解決辦法:把安裝目錄 /opt/dmdbms/bin
下的所有 .so
文件都拷貝到 docker 中
for i in `ls /opt/dmdbms/bin/*.so`; do echo $i ;docker cp $i bed496495fee:/opt/dmdbms/bin/; done
=>[IM004][unixODBC][Driver Manager]Driver’s SQLAllocHandle on SQL_HANDLE_HENV failed
odbcinst.ini
中配置的 Driver libdodbc.so
必須得是達夢的,不能是UnixODBC自己生成的
=> cannot find -lodbc
報錯詳情:
root@Kylin:/Users/liutongtong/go/src/dameng-test/main# go run beego-orm.go
# github.com/alexbrainman/odbc/api
/usr/lib/gcc-cross/arm-linux-gnueabi/8/../../../../arm-linux-gnueabi/bin/ld: cannot find -lodbc
/usr/lib/gcc-cross/arm-linux-gnueabi/8/../../../../arm-linux-gnueabi/bin/ld: cannot find -lodbc
使用 ld
命令查看:
root@Kylin:/Users/liutongtong/go/src/dameng-test/main# ld /usr/local/lib/libodbc.so
ld: warning: cannot find entry symbol _start; not setting start address
ld: /usr/local/lib/libodbc.so: undefined reference to `dlopen'
ld: /usr/local/lib/libodbc.so: undefined reference to `dlclose'
ld: /usr/local/lib/libodbc.so: undefined reference to `dlerror'
ld: /usr/local/lib/libodbc.so: undefined reference to `dlsym'
按照網上搜索來的方法進行嘗試:
重新編譯:
./configure LIBS=-ldl CFLAGS=-fno-strict-aliasing --build=armconfigure的時候提示:
checking for shl_load... (cached) no
checking for shl_load in -ldld... (cached) no
checking for dld_link in -ldld... no
checking for _ prefix in compiled symbols... no嘗試:
root@Kylin:/usr/local/lib# ar -x libodbcinst.a
root@Kylin:/usr/local/lib# gcc -shared *.o -o libodbcinst.so -ldl之后 ld 報錯:
root@Kylin:/Users/liutongtong/go/src/dameng-test/main# ld /usr/local/lib/libodbc.so
ld: warning: cannot find entry symbol _start; not setting start address
總之是越做越錯,越嘗試越絕望。
這個問題后來通過重新拉鏡像解決了。原來是我在瘋狂的改環境的時候,無意間造成了破壞。
幸好是在 Docker 里,沒有對他人造成影響。
這個故事告訴我們:一團亂麻的時候,不妨重新來過
地址:https://www.jianshu.com/p/7ad3b055d847