Postgres 14 Foreign Data Wrapper执行命令遇子进程退出码1问题排查
Postgres 14 file_fdw 调用 sudo 命令失败排查
问题场景
使用Postgres 14的file_fdw通过PROGRAM选项调用系统命令时,ps命令能正常返回结果,但sudo journalctl命令在命令行以postgres用户身份可执行,通过FDW调用却报错child process exited with exit code 1。
正常执行的命令示例
CREATE FOREIGN TABLE IF NOT EXISTS rawdata.system_ps ( pid text, started text, cpu_pcnt text, mem_pcnt text, command text ) SERVER "import" options ( PROGRAM 'ps --no-headers -e -o %p, -o lstart -o ,%C, -o %mem -o ,%c', FORMAT 'csv', HEADER 'true' ); -- select * from rawdata.system_ps;
执行失败的命令示例
CREATE FOREIGN TABLE IF NOT EXISTS rawdata.logs ( result text ) SERVER "import" options ( PROGRAM 'sudo journalctl -u postgrest.service --since "5 min ago" -o short-iso --no-pager', FORMAT 'text', --text, csv, or binary HEADER 'off' ); select * from rawdata.logs;
原因分析
- sudo 的 TTY 要求:sudo默认配置可能包含
requiretty选项,要求执行sudo的进程必须有终端(TTY)。但Postgres通过file_fdw调用外部命令时,是以非交互式、无TTY的方式运行,触发sudo的安全限制导致执行失败。而命令行下postgres用户有TTY,所以能正常执行。 - 环境变量差异:Postgres进程的环境变量集合与postgres用户交互式shell的环境不同,比如
PATH可能更受限,或者缺少sudo依赖的某些变量(如HOME),导致sudo执行时无法正确验证权限或找到命令。 - sudoers 规则的上下文限制:即使sudoers里允许postgres用户无密码执行journalctl,某些规则可能仅针对交互式会话生效,非交互式调用时不匹配。
解决步骤
修改sudoers配置,跳过TTY验证:
使用visudo编辑sudoers文件,添加以下规则(确保路径与实际journalctl路径一致):# 允许postgres用户无密码执行journalctl postgres ALL=(ALL) NOPASSWD: /usr/bin/journalctl # 给postgres用户豁免requiretty要求 Defaults:postgres !requiretty使用命令绝对路径:
将FDW命令中的journalctl替换为绝对路径(如/usr/bin/journalctl),避免因Postgres环境PATH受限导致命令找不到:PROGRAM 'sudo /usr/bin/journalctl -u postgrest.service --since "5 min ago" -o short-iso --no-pager',模拟非交互式环境测试:
切换到postgres用户,用非交互式方式测试命令是否能执行,验证配置是否生效:su - postgres -c "sudo /usr/bin/journalctl -u postgrest.service --since '5 min ago' -o short-iso --no-pager"如果此命令能正常输出,说明FDW调用也能正常工作。
内容的提问来源于stack exchange,提问作者Steve Lloyd
相关产品推荐
相关产品推荐

