“参数列表太长”对每一个指令

问题描述:

偶尔,当我有一个生成大型阵列我得到这个错误,每一个命令引发错误 “参数列表太长”即使 我只需键入一个程序:“参数列表太长”对每一个指令

$ cp 
-bash: /bin/cp: Argument list too long 
$ 

我不能使用ls,甚至打开一个新的文件,vim

$ vim test.txt 
-bash: /usr/bin/vim: Argument list too long 
$ 

我试图用“等待”的所有BG进程完成,但没有任何变化。它似乎不一致,但是当它发生时,唯一的解决方法是重新启动shell。

任何想法可能会发生什么?

更新:我做了一些进一步的测试,我得到的错误是可重复的。它发生在递归定义的数组长度达到85个元素时。引发错误的第一个命令是一个bc,它甚至不依赖于数组!然后从那里开始,几乎所有其他命令都会抛出相同的错误。

更新:我使用的程序有一起工作很多的bash脚本,但我已经决定的问题总是出现在这一个:

function MPMDrun_prop() 
{ 
PARDIR=$1 
COMPDIR=$2 
runSTR=$3 
NUMNODES=$4 
ForceRun=$5 

if [ $# -le 3 ] ; then 
echo "USAGE: MPMDrun_prop \$PARDIR \$COMPDIR \$runSTR \$NUMNODES \$ForceRun" 
fi 
echo "in MPMDrun_Prop" 
. $PARDIR/ParameterScan.inp 
. $MCTDHBDIR/Scripts/get_NumberOfJobs.sh 

if [ "$MPMD" != "T" ]; then 
    MPMDnodes=1 
fi 

## If no runscripts in the $PARDIR, copy one and strip of the line which runs the program 
if [ -z "$(ls $PARDIR/run*.sh 2> /dev/null)" ] ; then 

if [ "$forhost" == "maia" ]; then 
    cp $MCTDHBDIR/../PBS_Scripts/run-example-maia.sh $PARDIR/run.tmp 
    sed 's|mpirun.*||' < $PARDIR/run.tmp > $PARDIR/run.sh 
    jobtime=86400 
elif [ "$forhost" == "hermit" ]; then 
    cp $MCTDHBDIR/../PBS_Scripts/run-example-hermit.sh $PARDIR/run.tmp 
    sed 's|aprun.*||' < $PARDIR/run.tmp > $PARDIR/run.sh 
    jobtime=86400 
elif [ "$forhost" == "hornet" ]; then 
    cp $MCTDHBDIR/../PBS_Scripts/run-example-hornet.sh $PARDIR/run.tmp 
    sed 's|aprun.*||' < $PARDIR/run.tmp > $PARDIR/run.sh 
    jobtime=86400 
elif [ "$forhost" == "bwgrid" ]; then 
    cp $MCTDHBDIR/../PBS_Scripts/run-example-BWGRID.sh $PARDIR/run.tmp 
    sed 's|mpirun.*||' < $PARDIR/run.tmp > $PARDIR/run.sh 
    jobtime=86400 
fi 
sed 's|nodes=[0-9]*|nodes=0|' < $PARDIR/run.sh > $PARDIR/run.tmp 
sed 's|#PBS -N.*|#PBS -N MONSTER_'$MonsterName'|' < $PARDIR/run.tmp > $PARDIR/run.sh_ 

rm $PARDIR/run.sh 
rm $PARDIR/run.tmp 
chmod 755 $PARDIR/run.sh_ 
echo ". $MCTDHBDIR/Scripts/RunFlagSleeper.sh" >> $PARDIR/run.sh_ 
## Include check_convergence.sh for mixed relax/prop compatibility 
echo ". $MCTDHBDIR/Scripts/check_convergence.sh" >> $PARDIR/run.sh_ 
echo "RunFlagSleeper $jobtime " >> $PARDIR/run.sh_ 
echo "(" >> $PARDIR/run.sh_ 
cp $PARDIR/run.sh_ $PARDIR/run1.sh 
fi 
### Add $runSTR to the most recent runscript 
### find runscript$N.sh (run1.sh, run 2.sh, etc) that has numnodes less than $MPMDnodes 
for qq in $(ls $PARDIR/run[0-9]*.sh | sort -g); do 
    NodesInRun=$(cat $qq | grep -o "nodes *= *[0-9]*" | grep -o "[0-9]*") 
    if [ "$NodesInRun" -lt "$MPMDnodes" ]; then 
    ## The number of nodes already specified in the runscript doesnt exceed the maximum, so add on another job 
    NewNodes=$(echo "$NodesInRun+$NUMNODES" | bc) 
    ## Start each aprun command in its own subshell 
    ## wait for 24 hrs after aprun, to guarantee that no subshell finishes before the job is done 
    sed 's|nodes=[0-9]*|nodes='$NewNodes'|' < $qq > $qq-1 
    sed 's|\(RunFlagSleeper .*\)|\1 '$COMPDIR'|' <$qq-1 >$qq 
    rm $qq-1 
    echo " (" >> $qq 
    ## Sleeps for $jobtime - 5 mins, then removes runflag. in case aprun doesnt finish in $jobtime 
    echo " cd $COMPDIR" >> $qq 
    echo " $runSTR" >> $qq 
    ## remove runflag after aprun command has finished 
    echo " rm $COMPDIR/RunFlag" >> $qq 
#  echo "sleep $jobtime" >> $qq-1 
    echo " ) &" >> $qq 
# mv $qq-1 $qq 
    ## put a flag in the computation directory so it isnt computed multiple times 
    touch $COMPDIR/RunFlag 

    if [[ "$NewNodes" -ge "$MPMDnodes" || "$ForceRun" == "T" ]]; then 
    ## This last process made the nodecount exceed the maximum, or there is a ForceRun flag passed 
    ## So now, exceute the runscript and start another 
    echo " wait" >> $qq 
    echo ") &" >> $qq 
    echo "PID=\$!" >> $qq 
    echo "wait \$PID" >> $qq 
    ## Ensure the queue has room for the next job, if not, wait for it 
    Njobs=$(get_NumberOfJobs $runhost) 
    while [ "$Njobs" -ge "$maxjobs" ]; do 
    echo "Njobs=$Njobs and maxjobs=$maxjobs" 
    echo "Waiting 30 minutes for que to clear" 
    sleep 1800 
    done 
    echo "qsub $qq" 
# qsub $qq 
    RunCount=$(echo $qq | grep -o 'run[0-9]*.sh' | grep -o '[0-9]*') 
    let "RunCount++" 
    cp $PARDIR/run.sh_ $PARDIR/run$RunCount.sh 
    fi 
    fi 
done 
} 

的错误通常开始于80-90'th在第一个cpbc调用此函数。我已经评论过所有的数组操作,所以这是由于数组太大造成的。环境保持在〜100-200 Kb,这也不是问题。

+0

不要背景。只需将它放在前台,并启动一个_new_ shell来完成其他任务。这不像你会在Windows上拥有资源配额:-) – paxdiablo 2014-10-09 01:34:58

+0

也许我不清楚, 主要功能不在bg中。我只在这个应用程序中使用bg进行一些并行复制。 我刚刚尝试使用“等待”,因为我不知道还有什么要做。 – 2014-10-09 02:33:38

+0

检查你是否已经设置了'ulimit -s 0'或者等价的(使用'ulimit -s'来找到KiB中进程的最大堆栈大小)。如果堆栈大小太小(和/或您的环境太大),您将无法创建任何进程。当然,由于你不能运行'cp',你将不能运行'ulimit -s',这就让我们处于Catch-22状态。你可以运行另一个终端窗口并分析'/ dev/proc/NNNN',其中'NNNN'是不能运行任何东西的shell的PID? (如果你知道任何大的变量,你也许可以解开一些环境变量。) – 2014-10-09 04:12:30

该错误消息有点令人误解。应该说“参数列表和环境使用太多空间”。

环境由您已导出的所有环境变量以及shell启动的环境组成。通常情况下,环境应该只有几千字节,但是没有任何东西会阻止你从一百万字节的字符串中取得数据,如果你这样做了,你将用尽所有允许的空间。

系统允许多少空间参数+环境并不完全明显。你应该能够通过getconf ARG_MAX查询限制,并且用Gnu xargs可以从xargs --show-limits </dev/null获得更多信息(在这两种情况下,假设你还没有超出限制:)),但有时候实际的可用空间会变成小于所指示的。

无论如何,尝试将兆字节填充到环境中并不是一个好主意。如果您想要这么做,请将数据放在临时文件中,然后导出文件的名称。

+0

我的数组肯定不是兆字节。他们最多只能有几百个元素。当数组大小达到85时,我会一直遇到这个错误!我检查了最大的环境负荷,并且比我预期的要大几个数量级。不幸的是,当错误发生时,我无法运行xargs或getconf来确认。 – 2014-10-10 02:25:56

+0

数组不能导出,因此问题可能在其他地方。我应该提到这一点。你可以在纯bash中计算导出变量的总大小......我将这个咒语添加到答案中。 – rici 2014-10-10 05:37:33

+0

我插入'echo“test”| xargs --show-limits'到我的函数中,这样我就可以跟踪运行时的环境大小。 '你的环境变量占用的参数长度(本系统)147121 bytes' 'POSIX上限:4611686018427238734' 'POSIX最小的允许上限的争论长度(所有系统):4096' '最大长度我们实际可以使用的命令:4611686018427091613' '我们实际使用的命令缓冲区的大小:131072' 看起来环境比应该允许的要小得多。 – 2014-10-14 14:39:35

既然你说过,当你有一个生成大型数组的程序时,你会得到这个错误,其中每个命令都会抛出错误“参数列表太长”。所以,我认为你执行的最后一条命令会导致下一条命令出现问题。我的建议是,不要为任何命令使用大的参数列表。这可能会导致环境溢出,即使下一个命令也会出现问题。而不是大的参数列表,使用具有数据列表的文件,并使用文件重定向输入,如下所示:

command < inputfile 
+1

运行没有参数的'cp'几乎不使用大的参数列表。 – 2014-10-09 04:16:50

+0

由于某些命令的早期运行而引起的问题 – 2014-10-09 04:19:42

+0

您必须解释您在想什么;这对我来说没有多大意义。 – 2014-10-09 04:21:15