执行命令时加 sudo 出现 error while loading shared libraries: cannot open shared object file

最近在为直播系统增加三方转推功能时, 发现服务在执行转推命令时出现错误:

/usr/local/ffmpeg/3.1.2/bin/ffmpeg: error while loading shared libraries: liblenthevcenc.so: cannot open shared object file: No such file or directory

当时登录物理机,执行上面的 ffmpeg 命令,并未有错,如图:

执行命令时加 sudo 出现 error while loading shared libraries: cannot open shared object file_第1张图片

但注意到我登录时执行的身份是普通用户, 而服务是以 sudo 方式执行的,会不会在这一点差别上造成了上面不同的结果;因此尝试在 ffmpeg 命令前加上 sudo ,结果如下:

那直接原因已经清楚了,是否加 sudo 会出现不同的结果,那现在来分析下为什么。

先看 sudo 的官方介绍,允许用户以超级用户或者其他用户的身份执行安全策略允许的命令,

sudo allows a permitted user to execute a command as the superuser or another user, as specified by the security policy.

下面是安全策略配置文件,可以看到, root 用户可以执行所有命令, 而 dev group 的用户只允许执行除 DEV_DENIED 之外的命令:

/etc/sudoers

## Denied commands for dev
Cmnd_Alias DEV_DENIED = /bin/su, /usr/sbin/visudo, /usr/sbin/adduser, /usr/sbin/useradd, /usr/sbin/usermod, 
/usr/sbin/userdel, /usr/bin/passwd, /sbin/shutdown, /sbin/init, /sbin/reboot, /usr/bin/reboot, /sbin/halt, /sbin/poweroff,
 /sbin/fdisk, /sbin/sfdisk, /sbin/parted, /sbin/partprobe, /bin/mount, /bin/umount, /usr/bin/chattr

## Allow root to run any commands anywhere
root    ALL=(ALL)       NOPASSWD: ALL

## Allows members of the 'sa' group to run any commands anywhere
%sa    ALL=(ALL)       NOPASSWD: ALL

## Allows members of the 'dev' group to run any commands except DEV_DENIED anywhere
%dev    ALL=(ALL)       ALL, !DEV_DENIED
#includedir /etc/sudoers.d

那么 sudo 可以切换到超级用户和其他用户,默认情况是超级用户,这一点可以从它 -u 选项的说明看出:

-u user, --user=user
Run the command as a user other than the default target user (usually root).

现在已经清楚命令加 sudo 与否的区别了。

本文遇到的问题是以 root 身份执行 ffmpeg 时出现了找不到动态库 liblenthevcenc.so 的错误,

但该库已存在于 /usr/local/lib64/liblenthevcenc.so,且环境变量 LD_LIBRARY_PATH 包含了 /usr/local/lib64/;

显然 root 身份在查找动态库的时候并未使用到 LD_LIBRARY_PATH;(否则可以找到该库);

为了进一步确认,我以 root 身份登录,而不是加 sudo,发现 ffmpeg 并未出错:

执行命令时加 sudo 出现 error while loading shared libraries: cannot open shared object file_第2张图片

然后谷歌了一下,发现在 stackexchange 已经有类似的讨论:

Allowing LD_LIBRARY_PATH for suid binaries like sudo is a security problem, thus LD_LIBRARY_PATH gets 
stripped out of the environment. sudo by default doesn't passthrough LD_LIBRARY_PATH to its children either for 
the same security concerns: carefully crafted libraries would allow you to bypass the sudo argument restrictions to
 execute whatever you want.

If you need a variable set like this either use sudo -E, or pass the env variables on the command line like so: sudo 
-- LD_LIBRARY_PATH=/usr/local/lib dc_full. sudo will have to be configured to allow you to pass environment 
variables, which usually does not need manual configuration.

原因在于,为了安全考虑使用 sudo 执行的命令并不会包含环境变量 LD_LIBRARY_PATH,如果要使用,需要在执行 sudo 的时候通过 -E 选项显示的将 LD_LIBRARY_PATH 传到执行进程的环境中, 或者在脚本中通过 export 的方式传送 LD_LIBRARY_PATH。从而可以解决依赖的动态库无法找到的问题。

你可能感兴趣的:(linux)