bash脚本上的分段错误

时间:2015-02-07 14:16:45

标签: linux bash

我有一个bash脚本,在行

上显示“Segment Violation”
sp-sc-auth "${sopUrl}" 8809 8908 > /dev/null &

但是从终端执行sp-sc-auth时工作正常

我设置:

set -o pipefail
set -o errexit
set -o xtrace
set -o nounset

结束脚本继续执行但抛出“Segment Violation”错误...

系统是debian 64位

提前致谢 Regars

丑陋的代码:

#!/usr/bin/env bash
# Init
set -o pipefail
set -o errexit
#set -o xtrace
set -o nounset

__DIR__="$(cd "$(dirname "${0}")"; echo $(pwd))"
__BASE__="$(basename "${0}")"
__FILE__="${__DIR__}/${__BASE__}"

ARG1="${1:-Undefined}"

display_usage() {
    scriptName=$(basename $0)   
    echo -e "Uso:\n "${scriptName}" [6,7,8,9,10 o 12]"
    echo "Sin especificar el canal, búsqueda de retransmisiones"
}

parse_arenavision() {
url="http://www.arenavision.in/agenda"

if ! av=$(curl -s "${url}");then
    echo "Sin conexión"
    exit 1
fi
started="off"
declare -a _list
element=""

while read line
do
if [[ $line =~ (([0-9][0-9]+/[0-9]+/[0-9]+.*)) ]]; then
    element=$(echo "${BASH_REMATCH[0]}" | sed -r 's#CET|AV([^6789]|1[02])##g; s#<br />##g; s#//|&.*;##g; s#/\s*$##g; s#INGLATERRA/PREMIER LEAGUE#PREMIER#g; s#ITALIA/SERIE A#SERIE A#g; s#ITALIA/SERIE A#SERIE A#g;' | tr -dc '[:print:]')
    if [[ "${element}" =~ (.*AV[6789]|.*AV10|.*AV12) ]]; then
    _list+=("${element}")
    fi
    started="on"
else
    if [[ ${started} == "on" ]]; then
        break
    fi
fi
done <<< "${av}"

for i in "${_list[@]}"; do
    if [[ "${i}" =~ (.*BALONCESTO.*) ]]; then
        echo -e "\e[92m${i}\e[0m"
    elif [[ "${i}" =~ (.*LIGA BBVA.*) ]]; then
        echo -e "\e[37m${i}\e[0m"
    else 
        echo "${i}"
    fi
done

}

case $ARG1 in
    "Undefined" )
        parse_arenavision
        exit 0
        ;;
    [6789] )
        page="${ARG1}"
        ;;
    10 )
        page="${ARG1}"
        ;;
    * )
        display_usage
        exit 1
        ;;
esac

# Delete "zombies"
if pgrep -f "sp-sc"
then
    kill -9 `pgrep -f "sp-sc-auth"`
fi

url="http://www.arenavision.in/arenavision$page"

# Get url content and url sop
if ! content=$(curl -s "${url}");then
    echo "Sin conexión"
fi

if [[ $content =~ (sop://([A-Za-z0-9_]+|\.)+:[0-9]+) ]]; then
    sopUrl=${BASH_REMATCH[1]}
else
    echo "No se ha encontrado la url"
    exit 1
fi

# Connect ArenaVision 1
children=""
trap 'kill $children 1>/dev/null 2>&1; exit 143' EXIT

sp-sc-auth "${sopUrl}" 8809 8908 > /dev/null &
children="$!"

# Check if exists
line='[                ]'
for i in {0..15}
do
replace="${line/ /#}"
line=$replace
echo -ne "Comprobando sopcast  ${replace}" \\r
sleep 1
done
echo -ne "\033[2K"

if ! kill -0 "${children}" 1>/dev/null 2>&1; then
    echo "Sin emisión"
    exit 1
else
    echo -ne "Comprobando sopcast  [ OK ]" \\r
    echo
fi

# Open VLC player
line='[                          ]'
for i in {0..25}
do
replace="${line/ /#}"
line=$replace
echo -ne "Cargando reproductor ${replace}" \\r
sleep 1
done
if ! kill -0 "${children}" 1>/dev/null 2>&1; then
    echo "Fallo en recepción"
    exit 1
else
    vlc http://localhost:8908/tv.asf 1>/dev/null 2>&1
    echo -ne "\033[2K"
fi

exit 0

1 个答案:

答案 0 :(得分:1)

errexit 无法处理在后台运行的程序,所以这并不奇怪 - 内联命令只是启动后台进程,并且(启动后台进程)成功,即使过程本身随后失败。

如果您随后致电wait $!,则然后 errexit将能够生效,因为wait来电将以程序的退出状态退出本身。 (当然,如果你可以调用wait $!,那么就会提出你为什么要开始初始化程序的问题。


如果你总是想要在孩子失败时杀死父脚本,你可以这样做:

(sp-sc-auth "$sopUrl" 8809 8908 >/dev/null || kill $$) &

$$计算父shell的PID,而不是子shell,因此这将采取相应的行动。


至于段错本身,“程序X段错误”是一个太模糊的问题,无法在这里解决。要开始调试,你需要收集在失败时创建的核心转储(如有必要,启用核心),安装sopcast的调试符号,并使用gdb从失败时创建的核心文件中收集堆栈跟踪。