【问题标题】:WHILE loop not loopingWHILE 循环不循环
【发布时间】:2014-04-19 06:41:07
【问题描述】:

我对 Linux 和 shell 脚本还很陌生。

我的问题是,脚本应该从名为“list”的文件中读取 2 个令牌 - 使用这些令牌,它会创建一个用户,并根据第二个令牌创建一个子文件夹。它这样做很好 - 但只有一次。只有一次。我的 WHILE 循环有问题吗?

以下是“列表”中的几行示例:

egyes n
kettes y
harmas y

这是脚本:

#!/bin/bash
echo " " >> /root/userpass.txt
most=$(date)

while read user rr; do
    p1=${user:0:2}
    p2=${user:3:4}
    pass=$p1$RANDOM$p2
    echo $user - $pass --" LÉTREHOZVA: "$most >> /root/userpass.txt

    adduser $user > /dev/null
    echo $user:$pass | chpasswd > /dev/null

    uhome=/home/$user

    if [ $rr=="y" ]; then
            mkdir $uhome/rockandroll
            chown $user $uhome/rockandroll
    fi

    mkdir $uhome/res-devres
    chown $user $uhome/res-devres

    ftpc=/etc/proftpd/proftpd.conf

    echo "#"$1 >> $ftpc
    echo "<Directory "$uhome"/res-devres/>" >> $ftpc
    echo '  <Limit CDUP XCUP STOR LIST CWD XCWD STOU>' >> $ftpc
    echo '          AllowAll' >> $ftpc
    echo '  </Limit>' >> $ftpc
    echo '  <Limit RETR DELE>' >> $ftpc
    echo '          DenyAll' >> $ftpc
    echo '  </Limit>' >> $ftpc
    echo '</Directory>' >> $ftpc
    echo " " >> $ftpc
    echo " "
done < list

提前致谢。

【问题讨论】:

  • 吃东西的标准输入?
  • 注意:将密码存储为纯文本是个坏主意...
  • 它是临时使用的,直到我将它们发送出去。之后我删除了文件,但这不是重点。你是什​​么意思“吃标准输入”?
  • 任何从标准输入读取的进程都会处理循环的输入。你可以通过简单的消除找到它..
  • 是的,可能就是这样 - 在完成工作后如何阻止它访问标准输入?

标签: linux bash shell while-loop


【解决方案1】:

改变

if [ $rr=="y" ]; then

if [ $rr == "y" ]; then

【讨论】:

    【解决方案2】:

    正如 cmets 中所指出的,循环中的某些命令正在从标准输入中读取。您可以找出是哪个命令,并从/dev/null 重定向其标准输入:

    bad_command < /dev/null
    

    或者简单地为 while 循环使用不同的文件描述符:

    while read user rr <&3; do
        ...
    done 3< list
    

    现在read 命令不是从标准输入读取,而是从文件描述符 3 读取,循环体中的任何命令都不太可能使用它。


    正如宝马所指出的,您需要修复您的if 声明:

    if [ "$rr" = "y" ]; then
    

    等号周围的空格是必要的,因为[ 是一个命令,不是if 语法的一部分,它需要3 个不同的参数($rr="y");它不会解析单个字符串 $rr="y" 作为比较。 =[ 命令的首选,因为通常 == 不是 POSIX 相等比较运算符。但是,bash 确实允许 ==,但也提供了一个高级命令,它不需要 $rr 以使用 [ 进行安全引用:

    if [[ $rr == y ]]; then    # == or = will work the same
    

    您可以通过将echo 语句组合成一个复合命令并将它们的组合输出重定向一次,从而在循环的最后部分节省一些输入:

    {
        echo ...
        echo ...
        echo ...
    } > "$ftpc"
    

    tripleee 指出的另一个选项只需要一次调用cat。它产生一个外部进程,但看起来更干净。

    cat > "$ftpc" <<EOF
    #$1
    <Directory $uhome/res-devres/>
    etc
    EOF
    

    您也可以只使用 echo 和一个带有嵌入换行符的字符串。

    echo "#$1
    <Directory $uhome/res-devres/>
    etc
    " > "$ftpc"
    

    【讨论】:

    • echo 的痛苦也可以通过使用 here 文档来缓解。
    猜你喜欢
    • 2016-04-24
    • 2023-03-10
    • 2010-11-26
    • 2020-11-26
    • 2013-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多