You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何脚本中使用空分隔符时printf退出码为1?

Bash脚本中printf '%s\0%s\0'退出码为1的问题

我编写了一段Bash脚本,其中的printf '%s\0%s\0'命令退出码为1,即使强制使用Bash 5.2版本,结果依旧相同。

示例脚本

#!/usr/bin/env bash
echo $BASH_VERSION
set -x
set -Eeuo pipefail

function prompt_creds {
  local username password
  read -rp "username " username
  read -rsp "password " password 
  printf '%s\0%s\0' "${username}" "${password}"
}

function main() {
  IFS=$'\0' read -r username password < <(prompt_creds )
  echo "我的用户名是 ${username}" "我的密码是 ${password}"
}

main

脚本运行输出

./sample.sh 
3.2.57(1)-release
+ set -Eeuo pipefail
+ main
+ IFS=
+ read -r username password
++ prompt_creds
++ local username password
++ read -rp 'username ' username
username user
++ read -rsp 'password ' password
password ++ printf '%s\0%s\0' user pass
bash-5.2$ echo $?
1

命令行直接运行正常

bash-5.2$ IFS=$'\0' read -r u p < <(printf '%s\0%s\0' user pass)
bash-5.2$ echo $u $p
user pass

问题原因

核心问题在于read -r username password的行为:当它读取到两个以空字符分隔的字段(即输入的user和pass)后,会立即关闭输入管道,不再读取后续数据。而printf '%s\0%s\0'会输出user\0pass\0,最后那个额外的空字符会让printf尝试向已关闭的管道写入数据,触发SIGPIPE信号,导致printf异常退出。

在多数Bash环境中,被SIGPIPE终止的命令退出码为141(128+13,13是SIGPIPE的信号编号),你看到的退出码为1可能是环境差异或测试方式导致,但本质原因都是管道提前关闭引发的信号终止。

解决方法

修改printf的输出,去掉末尾多余的空字符,确保输出的内容刚好匹配read需要的两个字段:

printf '%s\0%s' "${username}" "${password}"

修改后,printf输出user\0pass,read读取完所有需要的数据后,管道正常关闭,printf可以正常退出,退出码为0,脚本也会执行到最后的输出语句。

内容的提问来源于stack exchange,提问作者Christian Bongiorno

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 16:57:24