bash命令并行

时间:2013-02-15 17:53:46

标签: bash

我希望有两个youtube-dl进程(或尽可能多)并行运行。请告诉我如何。提前谢谢。

#!/bin/bash
#package: youtube-dl axel

#file that contains youtube links
FILE="/srv/backup/temp/youtube.txt"

#number of lines in FILE
COUNTER=`wc -l $FILE | cut -f1 -d' '`

#download destination
cd /srv/backup/transmission/completed

if [[ -s $FILE ]]; then
  while [ $COUNTER -gt 0 ]; do

    #get video link
    URL=`head -n 1 $FILE`

    #get video name
    NAME=`youtube-dl --get-filename -o "%(title)s.%(ext)s" "$URL" --restrict-filenames`

    #real video url
    vURL=`youtube-dl --get-url $URL`

    #remove first link
    sed -i 1d $FILE

    #download file
    axel -n 10 -o "$NAME" $vURL &

    #update number of lines
    COUNTER=`wc -l $FILE | cut -f1 -d' '`
  done
else
  break
fi

4 个答案:

答案 0 :(得分:2)

这应该与GNU Parallel一起使用:

cd /srv/backup/transmission/completed
parallel -j0 'axel -n 10 -o $(youtube-dl --get-filename -o "%(title)s.%(ext)s" "{}" --restrict-filenames) $(youtube-dl --get-url {})' :::: /srv/backup/temp/youtube.txt

了解详情:https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1

答案 1 :(得分:1)

解决方案

您需要运行command in a subshell,即将命令输入( cmd ) &

定义

  

shell脚本本身可以启动子进程。这些子壳让   脚本执行并行处理,实际上执行多个子任务   同时进行。

代码

对于你来说,我猜是这样的(我在$vURL添加引号):

( axel -n 10 -o "$NAME" "$vURL" ) &

答案 2 :(得分:0)

我不知道这是不是最好的方法,你可以定义一个函数,然后在后台调用它

类似的东西:

#!/bin/bash
#package: youtube-dl axel

#file that contains youtube links
FILE="/srv/backup/temp/youtube.txt"

# define a function
download_video() {
  sleep 3
  echo $1
}

while read -r line; do
  # call it in background, with &
  download_video $line &
done < $FILE

脚本快速结束但功能仍然在后台运行,3秒后它将显示回声

还使用read和while循环来简化文件读取

答案 3 :(得分:0)

这是我的看法。通过避免几个命令,您应该看到速度有一些小的改进,尽管它可能不明显。我确实添加了错误检查,这可以节省您在损坏的URL上的时间。

#file that contains youtube links
FILE="/srv/backup/temp/youtube.txt"

while read URL ; do
    [ -z "$URL" ] && continue

    #get video name
    if NAME=$(youtube-dl --get-filename -o "%(title)s.%(ext)s" "$URL" --restrict-filenames) ; then
        #real video url
        if vURL=$(youtube-dl --get-url $URL) ; then
            #download file
            axel -n 10 -o "$NAME" $vURL &
        else
            echo "Could not get vURL from $URL"
        fi
    else
        echo "Could not get NAME from $URL"
    fi
done << "$FILE"

根据要求,这是我提出的并行vURL和NAME获取以及下载的建议。注意:由于下载取决于vURL和NAME,因此创建三个进程没有任何意义,其中两个为您提供最佳回报。下面我将NAME fetch放在它自己的进程中,但是如果事实证明vURL一直更快,那么使用NAME提取交换它可能会有一个小小的回报。 (这样下载过程中的while循环不会浪费第二次睡眠。)注意2:这是相当粗糙的,未经测试的,它只是袖手旁观,可能需要工作。在任何情况下都可能有更酷的方式。害怕......

#!/bin/bash

#file that contains youtube links
FILE="/srv/backup/temp/youtube.txt"

GetName () {  # URL, filename
    if NAME=$(youtube-dl --get-filename -o "%(title)s.%(ext)s" "$1" --restrict-filenames) ; then
        # Create a sourceable file with NAME value
        echo "NAME='$NAME'" > "$2"
    else
        echo "Could not get NAME from $1"
    fi
}

Download () {  # URL, filename
    if vURL=$(youtube-dl --get-url $1) ; then
        # Wait to see if GetName's file appears
        timeout=300  # Wait up to 5 minutes, adjust this if needed
        while (( timeout-- )) ; do
            if [ -f "$2" ] ; then
                source "$2"
                rm "$2"
                #download file
                if axel -n 10 -o "$NAME" "$vURL" ; then
                    echo "Download of $NAME from $1 finished"
                    return 0
                else
                    echo "Download of $NAME from $1 failed"
                fi
            fi
            sleep 1
        done
        echo "Download timed out waiting for file $2" 
    else
        echo "Could not get vURL from $1"
    fi
    return 1
}


filebase="tempfile${$}_"
filecount=0

while read URL ; do
    [ -z "$URL" ] && continue
    filename="$filebase$filecount"
    [ -f "$filename" ] && rm "$filename" # Just in case
    (( filecount++ ))
    ( GetName "$URL" "$filename" ) &
    ( Download "$URL" "$filename" ) &
done << "$FILE"