首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Bash不按预期工作-如何调试它

Bash不按预期工作-如何调试它
EN

Stack Overflow用户
提问于 2016-05-23 16:23:18
回答 1查看 62关注 0票数 0

我被分配了以下任务。我们有一个二进制形式的预先构建的GUI,保存在$GAME_BIN中。我必须写一个脚本,连接GUI和人工智能引擎。这是我的代码,非常自我描述。我们在这个例子中有:GAME_BIN=./sredniowiecze_guiai1=./idle_ai.shai2=./idle_ai.sh

代码语言:javascript
运行
复制
#!/bin/bash

# arguments parsing and setting $args - not posting this here

gui_outpipe=$(mktemp -u)
gui_inpipe=$(mktemp -u)
ai1_outpipe=$(mktemp -u)
ai1_inpipe=$(mktemp -u)
ai2_outpipe=$(mktemp -u)
ai2_inpipe=$(mktemp -u)
mkfifo $gui_outpipe $gui_inpipe $ai1_outpipe $ai1_inpipe $ai2_inpipe $ai2_outpipe

printinit 1 > $ai1_inpipe &
printinit 2 > $ai2_inpipe &
$GAME_BIN $args < $gui_inpipe &
$ai1 < $ai1_inpipe > $ai1_outpipe &
$ai1 < $ai2_inpipe > $ai2_outpipe &
while true; do
    echo "Started the loop"
    while true; do
        read line < $ai1_outpipe || echo "Nothing read"
        echo $line
        if [[ $line ]]; then
            echo "$line" > $gui_inpipe
            echo "$line" > $ai2_inpipe
            if [[ "$line" == "END_TURN" ]]; then
                break
            fi
        fi
    done
    sleep $turndelay
    while true; do
        read line < $ai2_outpipe || echo "nothing read"
        echo $line
        if [[ $line ]]; then
            echo "$line" > $gui_inpipe
            echo "$line" > $ai2_inpipe
            if [[ "$line" == "END_TURN" ]]; then
                break
            fi
        fi
    done
    sleep $turndelay
done

wait

我创建了一个包含在idle_ai.sh中的简单的空闲AI

代码语言:javascript
运行
复制
#!/bin/sh
while true; do
    echo END_TURN
done

然后,根本没有接收到来自GUI的END_TURN消息。另一方面,脚本没有接收到行END_TURN中的第二个(*)。如果我使用我自己编写的人工智能--非常长的代码,不在此发布,则在while循环的第二次运行中,将不会收到来自AI的任何信息。

我完全不知道如何调试它。

由于我不急于运行二进制文件,所以我将通过firejail ./game.sh [irrelevant parameters]调用脚本

编辑在添加set -x之后,输出是

代码语言:javascript
运行
复制
INIT 10 3 1 1 1 3 9
+ [[ -n ./idle_ai.sh ]]
+ [[ -n '' ]]
+ [[ -n ./idle_ai.sh ]]
+ printinit 1
+ ./sredniowiecze_gui -human2
+ true
+ echo 'Started the loop'
Started the loop
+ true
+ read line
+ ./idle_ai.sh
+ echo 'INIT 10 3 1 1 1 3 9'
+ echo END_TURN
END_TURN
+ [[ -n END_TURN ]]
+ echo END_TURN
+ [[ END_TURN == \E\N\D\_\T\U\R\N ]]
+ break
+ true
+ read line
+ echo MOVE 5 9 5 8
MOVE 5 9 5 8
+ [[ -n MOVE 5 9 5 8 ]]
+ echo 'MOVE 5 9 5 8'

在AI对AI模式中:

代码语言:javascript
运行
复制
INIT 10 3 1 1 1 3 9
+ [[ -n ./idle_ai.sh ]]
+ [[ -n ./idle_ai.sh ]]
+ printinit 1
+ printinit 2
+ ./sredniowiecze_gui
+ ./idle_ai.sh
+ true
+ echo 'Started the loop'
Started the loop
+ echo 'INIT 10 3 1 1 1 3 9'
+ true
+ read line
+ ./idle_ai.sh
+ echo 'INIT 10 3 2 1 1 3 9'
+ echo END_TURN
END_TURN
+ [[ -n END_TURN ]]
+ echo END_TURN
+ echo END_TURN
+ [[ END_TURN == \E\N\D\_\T\U\R\N ]]
+ break
+ sleep 1
+ true
+ read line
+ echo END_TURN
END_TURN
+ [[ -n END_TURN ]]
+ echo END_TURN
+ echo END_TURN
+ [[ END_TURN == \E\N\D\_\T\U\R\N ]]
+ break
+ sleep 1
+ true
+ echo 'Started the loop'
Started the loop
+ true
+ read line

EDIT2我做了建议的更改,现在我的代码是:

代码语言:javascript
运行
复制
printinit 1 > $ai1_inpipe &
printinit 2 > $ai2_inpipe &
$GAME_BIN $args < $gui_inpipe &
$ai1 < $ai1_inpipe > $ai1_outpipe &
echo $!
$ai2 < $ai2_inpipe > $ai2_outpipe &
echo $!
while true; do
    echo "Started the loop"
    while true; do
        read -u3 line || echo "Nothing read"
        echo $line
        if [[ $line ]]; then
            echo "$line" > $gui_inpipe
            echo "$line" > $ai2_inpipe
            if [[ "$line" == "END_TURN" ]]; then
                break
            fi
        fi
    done
    sleep $turndelay
    while true; do
        read -u4 line || echo "nothing read"
        echo $line
        if [[ $line ]]; then
            echo "$line" > $gui_inpipe
            echo "$line" > $ai1_inpipe
            if [[ "$line" == "END_TURN" ]]; then
                break
            fi
        fi
    done
    sleep $turndelay
done 3<$ai1_outpipe 4<$ai2_outpipe

现在脚本被卡在echo "$line" > $ai1_inpipe行上了,尽管$ai2进程仍然在运行。

EDIT3.现在使用set -x的日志是

代码语言:javascript
运行
复制
INIT 10 3 1 1 1 3 9
+ [[ -n ./idle_ai.sh ]]
+ [[ -n ./idle_ai.sh ]]
+ printinit 1
+ printinit 2
+ ./sredniowiecze_gui
+ echo 26
26
+ ./idle_ai.sh
+ echo 'INIT 10 3 1 1 1 3 9'
+ echo 27
27
+ ./idle_ai.sh
+ echo 'INIT 10 3 2 1 1 3 9'
+ true
+ echo 'Started the loop'
Started the loop
+ true
+ read -u3 line
+ echo END_TURN
END_TURN
+ [[ -n END_TURN ]]
+ echo END_TURN
+ echo END_TURN
+ [[ END_TURN == \E\N\D\_\T\U\R\N ]]
+ break
+ sleep 1
+ true
+ read -u4 line
+ echo END_TURN
END_TURN
+ [[ -n END_TURN ]]
+ echo END_TURN
+ echo END_TURN

如果在调用之前和之后添加一个echo FOO,如下所示:

代码语言:javascript
运行
复制
            echo FOO
            echo "$line" > $ai1_inpipe
            echo BAR

然后执行echo FOO,而不执行echo BAR

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-05-23 18:38:15

您使用的是read < input,它吸收了所有输入,并且只使用第一行。不需要这样做,您应该从打开的文件描述符中读取read,如下所示:

编辑:与用echo写入fifo文件相同

代码语言:javascript
运行
复制
while true; do
echo "Started the loop"
while true; do
    read -u3 line || echo "Nothing read"
    ...
        echo "$line" >&5
        echo "$line" >&6
    ...
done
sleep $turndelay
while true; do
    read -u4 line || echo "nothing read"
    ...
        echo "$line" >&5
        echo "$line" >&7
    ...
sleep $turndelay
done 3<$ai1_outpipe 4<$ai2_outpipe 5>$gui_inpipe 6>$ai2_inpipe 7>$ai1_inpipe

有关该主题的更多帮助,请参见这些链接:

  • BashGuide命名管道
  • BashFAQ 085
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37395985

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档