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

Bash端口检测脚本在Zsh中无法运行的问题求助

Zsh环境下端口检测脚本修复方案

原Bash脚本(2015款MBP正常运行)

rogue() {
  local PORTS="1234 3000 4200 4567 5000 5432 6379 7777 7778 8000 8888 27017 9000 8080 8081"
  local MESSAGE="> Checking for processes on ports"
  local COMMAND="lsof"

  for PORT in $PORTS; do
    MESSAGE="${MESSAGE} ${PORT},"
    COMMAND="${COMMAND} -i TCP:${PORT}"
  done

  echo "${MESSAGE%?}..."
  local OUTPUT="$(${COMMAND})"

  if [ -z '$OUTPUT' ]; then
    echo "> Nothing running!"
  else
    echo "> Processes found:"
    printf "\n$OUTPUT\n\n"
    echo "> Use the 'kill' command with the 'PID' of any process you want to quit."
    echo "> Use 'kill -9 PID' to kill all duplicate processes"
    echo
  fi
}

Zsh环境下的错误表现

执行后报错,错误输出:

> Checking for processes on ports 1234 3000 4200 4567 5000 5432 6379 7777 7778 8000 8888 27017 9000 8080 8081...
rogue:11: command not found: lsof -i TCP:1234 3000 4200 4567 5000 5432 6379 7777 7778 8000 8888 27017 9000 8080 8081
> Processes found:



> Use the 'kill' command with the 'PID' of any process you want to quit.
> Use 'kill -9 PID' to kill all duplicate processes

修改后的问题脚本及输出

尝试改为数组存储端口,但遍历语法错误,脚本如下:

rogue() {
  ports=("1234" "3000" "4200" "4567" "5000" "5432" "6379" "7777" "7778" "8000" "8888" "27017" "9000" "8080" "8081")
  message="> Checking for processes on ports"
  command="lsof"

  for port in "{$ports[@]}"; do
    message="$message $port"
    command="$command -i TCP:$port"
  done

  echo "$message ..."
  output="$command"

  if [ -z "$output" ]; then
    echo "> Nothing running!"
  else
    echo "> Processes found:"
    printf "\n$output\n\n"
    echo "> Use the 'kill' command with the 'PID' of any process you want to quit."
    echo "> Use 'kill -9 PID' to kill all duplicate processes"
    echo
  fi
}

输出异常,仅打印命令字符串而非执行结果:

lsof -i TCP:{1234 -i TCP:3000 -i TCP:4200 -i TCP:4567 -i TCP:5000 -i TCP:5432 -i TCP:6379 -i TCP:7777 -i TCP:7778 -i TCP:8000 -i TCP:8888 -i TCP:27017 -i TCP:9000 -i TCP:8080 -i TCP:8081}

问题分析

  1. 原Bash脚本核心问题:Zsh中直接执行$COMMAND时,会将整个字符串视为单个命令名而非"命令+参数"组合,导致找不到对应命令。
  2. 修改后脚本问题:
    • 数组遍历语法错误:"{$ports[@]}"应为"${ports[@]}",多余引号导致数组被当作单个字符串处理。
    • 未实际执行命令:仅将命令字符串赋值给output,未执行并捕获结果。
  3. 额外问题:原脚本中[ -z '$OUTPUT' ]使用单引号,导致变量无法展开,永远判断为非空。

修复后的脚本

rogue() {
  # 用数组存储端口,避免分词歧义
  local ports=("1234" "3000" "4200" "4567" "5000" "5432" "6379" "7777" "7778" "8000" "8888" "27017" "9000" "8080" "8081")
  local message="> Checking for processes on ports"
  # 用数组存储命令和参数,Zsh下能正确解析
  local cmd=("lsof")

  for port in "${ports[@]}"; do
    message="${message} ${port}"
    cmd+=("-i" "TCP:$port")
  done

  echo "${message}..."
  # 执行命令并捕获输出
  local output="$("${cmd[@]}")"

  if [ -z "$output" ]; then
    echo "> Nothing running!"
  else
    echo "> Processes found:"
    printf "\n%s\n\n" "$output"
    echo "> Use the 'kill' command with the 'PID' of any process you want to quit."
    echo "> Use 'kill -9 PID' to force quit unresponsive processes"
    echo
  fi
}

关键修改点

  • 使用数组存储命令和参数:cmd=("lsof")和cmd+=("-i" "TCP:$port"),确保Zsh能正确识别命令与参数的边界,避免将整个字符串当作命令名。
  • 正确遍历数组:for port in "${ports[@]}",双引号包裹确保每个端口作为独立元素遍历。
  • 修复空值判断:[ -z "$output" ]使用双引号,让变量正常展开。
  • 执行命令时用"${cmd[@]}",确保参数正确传递给lsof。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 16:44:54