python - 在 ubuntu 上编译并在 SuSe 12 SP4 上运行的 Pyinstaller 子进程的奇怪行为
问题描述
我注意到在 Ubuntu 16 上使用 pyinstaller 编译的子进程的一些奇怪行为在 ubuntu 16 上运行良好,但在 SuSe12 SP4 上失败。想知道是否有人可以阐明并告诉我我错过了哪些微不足道的信息?
基本上,我有一个简单的脚本:
import os, sys, subprocess
def get_all_outputs(cmd):
proc = subprocess.Popen(cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
shell=True,
universal_newlines=True)
std_out, std_err = proc.communicate()
return proc.returncode, std_out, std_err
cmd = raw_input('CMD:')
print get_all_outputs(cmd)
这可以作为 Ubuntu 16 上的普通 python 文件或 pyinstaller 文件正常工作......
root@ubuntu16:~/cert/dist# ./retcode
CMD:openssl x509 -in /root/cert_new/mycert.cer
(0, '-----BEGIN CERTIFICATE-----\nMIIFmTCCBIGgAwIBAgITQwAAAGqQd2QfUVAHwQABAAAAajANBgkqhkiG9w0BAQsF\nADBGMRUwEwYKCZImiZPyLGQBGRYFbG9jYWwxFjAUBgoJkiaJk/IsZAEZFgZhdmFt\nYXIxFTATBgNVBAMTDGF2YW1hci1EQy1DQTAeFw0yMDEyMjkxMjAyNDhaFw0yMjEy\nMjkxMjAyNDhaMHYxCzAJBgNVBAYTAkFVMQwwCgYDVQQIEwNOU1cxDzANBgNVBAcT\nBlN5ZG5leTERMA8GA1UEChMIRGVsbCBFTUMxEDAOBgNVBAsTB1N1cHBvcnQxIzAh\nBgNVBAMTGm5lbzEtc3lWwMBMA0GCSqGSIb3DQEBCwUAA4IBAQBjH2ubfVxCC42LVURTZUog/vJZ\nctAEBDUW3VaeRCMWD3dvB0loc0llGaXQVafh0Q2cW8Uy0qMexPcUUwp8OjbtwcBo\n3TkEApBABgX/JC9P+BXCK3NiYze1SAjsgcdeZaS0t3HLlgwc8vZSotXco+mwZM9S\nTtrU1RqU4kkqhR5+wjPT8ffLFyZNBCdDKUOF3wxsr/0uUpfm9Bnt3DahoN4dwHvI\nOvi1DSV6ob84VXKT3ehMqt27ZW5dtLQdpzINADHDHlitTAUAO+CdO3LltqobQbf8\niK8fmnmSWHVF8vA3mmIfANLILZ6XKASgo2D2RU0jPjbkWi3nPY+2aRPGS1wJ\n-----END CERTIFICATE-----\n', '')
但是,当我将编译后的文件 scp 到 SuSe12SP4 时,我从未得到输出,而是不断抛出错误代码 127 以及如下所示的有趣消息:
neo_suse12sp4:~/pp # ./retcode
CMD:/usr/local/ssl/bin/openssl x509 -in /root/pp/mycert.cer
(127, '', '/bin/sh: /tmp/_MEIOqKDWs/libreadline.so.6: no version information available (required by /bin/sh)\n/usr/local/ssl/bin/openssl: relocation error: /usr/local/ssl/bin/openssl: symbol i2d_DHxparams, version OPENSSL_1.0.0 not defined in file libcrypto.so.1.0.0 with link time reference\n')
我什至尝试使用 openssl 和证书的完整路径,但它根本不起作用。
neo_suse12sp4:~/pp # which openssl
/usr/local/ssl/bin/openssl
如果有人可以在这里为我提供帮助,我将不胜感激。我会非常感谢你。谷歌和现有的关于 SO 的文章似乎无法解决这个问题。
解决方案
好吧,看来我自己找到了出路。这看起来像是在 SuSe 12 SP4 系统上找到的 openssl 可执行文件与从 Ubuntu 16 构建系统收集的 libcrypto.so 库不兼容(现在正在冻结应用程序及其子进程中覆盖系统一)。
我们需要修改子进程的 LD_LIBRARY_PATH 以使系统的库优先于捆绑的库。
非常感谢 github 上的 @Rok Mandeljc (rokm) 为我提供的帮助。在这里发布它以防其他人撞到头会很容易解决这个问题。
解决方案:
###Add the following code to your existing code
env = dict(os.environ) # make a copy of the environment
lp_key = 'LD_LIBRARY_PATH' # for GNU/Linux and *BSD.
lp_orig = env.get(lp_key + '_ORIG')
if lp_orig is not None:
env[lp_key] = lp_orig # restore the original, unmodified value
else:
# This happens when LD_LIBRARY_PATH was not set.
# Remove the env var as a last resort:
env.pop(lp_key, None)
接下来,将 env 变量添加到子进程 Popen 命令
def run_command(cmd): #returns the output of a program
proc = subprocess.Popen(cmd,stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, shell=True, universal_newlines=True, env=env)
std_out, std_err = proc.communicate()
return std_out
推荐阅读
- express - TypeORM NestJS:使用 MySQL/RDMS 管理数据库分片的最佳方法?
- python - 将 PostgreSQL 输出参数返回给 Python 会返回预先提交的值
- pytorch - 这个函数是如何通过切片来遍历token的,你能解释一下它是如何选择列表中的元素的吗?
- .htaccess - .htaccess 问题与 url
- python - 如何从 Python QuerySet 中检索值?
- python - 是否可以通过 API 将 Google Ads 自定义报告加载到生产数据库中
- python - Django 记录锁定和原子事务
- javascript - Google 的 People Api:无法从 Vuejs 应用程序获取组织信息
- react-native - 如何修改/替换 mobx-state-tree 中的所有存储?
- r - 如何知道我的数据是否遵循 R 中的两个参数或三个参数对数正态分布