向应用程序发送命令并通过 bash 中的文件描述符读取其输出

Sending commands to an application and reading its output via file descriptor in bash

bluetoothctl 是一个具有 shell 并接受输入命令的应用程序。我想从 linux 的 shell 任意地向它发送命令,我也想读取它的无颜色输出。我正在使用基于 debian 的 linux(Raspbian 破坏者),如果可能的话,我想从 bash shell 开始。

到目前为止我已经尝试过:

方法一(通过fd发送命令)

方法二(将输出写入文本文件)

方法三(通过管道发送命令)

我认为可行的解决方案是启动应用程序分离 $ bluetoothctl & 然后通过 /proc/$(pidof bluetoothctl)/fd/0 向它发送命令并通过 /proc/$(pidof bluetoothctl)/fd/1 和 [=23 读取它的标准输出和标准错误=] 但我完全迷路了。

我想执行并读取其输出的命令之一是 'scan on' 理想情况下,一个 bluetoothctl 实例将处理多个命令,而不仅仅是管道可以执行的命令。 有人可以建议如何通过 fd 发送命令,以及如何通过进程的另一个 fd 读取输出。如果可能,所有这些都在 bash shell 中。

coprocess 是适合这项工作的工具:

#!/usr/bin/env bash
case $BASH_VERSION in ''|[0-3].*|4.0*) echo "ERROR: bash 4.1+ required" >&2; exit 1;; esac

coproc btctl { bluetoothctl; }

echo "scan on" >&"${btctl[1]}"

while IFS= read -r -u "${btctl[0]}" line; do
  echo "Read line from btctl: $line" >&2
done

为了每个人的利益:按照接受的答案,我已经解决了我的协处理问题,但是,我使用 /proc/$(pidof bluetoothctl)/fd/0 发送命令,因为它的某些异步特性更适合我的应用程序.然后将输出转移到一个文件中,并在读取时使用 sed 删除颜色。

#!/bin/bash

readOutput() {
    echo "$(cat $TEMP/bluetoothctl.out | sed 's/\x1B\[[0-9;]\{1,\}[A-Za-z]//g'"
}

executeCommandInExistingProcess() {
  if [ -z "$(pidof bluetoothctl)" ]
  then
    exit -1
  else
    echo "" >&/proc/$(pidof bluetoothctl)/fd/0
  fi
}

startParallelProcess() {
  output="$TEMP/bluetoothctl.out"
  
  if [ ! -z "$(pidof bluetoothctl)" ]
  then
    echo "Bluetooth process is running..."
    exit -1
  fi
  
  if [ -f "$output" ]
  then
    rm $output
  fi

  coproc bctl { bluetoothctl > $output; }
  [ "$#" -ge 1 -a ! -z "" ] && executeCommandInExistingProcess ""

  sleep 30

  if [ ! -z $(pidof bluetoothctl) ]
  then
    [ "$#" -ge 2 -a ! -z "" ] && executeCommandInExistingProcess ""
    executeCommandInExistingProcess "quit"
  fi
}