bash脚本中的条件变量?

时间:2012-12-08 02:09:04

标签: bash

我不习惯用bash编写代码,但我自学了。我正在尝试创建一个将从进程列表中查询信息的脚本。我已经做到了,但我想进一步做到这一点:

  1. 如果存在A OS,脚本将使用一组命令运行。
  2. 如果存在B OS,脚本将使用不同的命令集运行。
  3. 这是我到目前为止所拥有的。它适用于我的Centos发行版但不适用于我的Ubuntu。非常感谢任何帮助。

    #!/bin/bash
    
    pid=$(ps -eo pmem,pid | sort -nr -k 1 | cut -d " " -f 2 | head -1)
    howmany=$(lsof -l -n -p $pid | wc -l)
    nameofprocess=$(ps -eo pmem,fname | sort -nr -k 1 | cut -d " " -f 2 | head -1)
    percent=$(ps -eo pmem,pid,fname | sort -k 1 -nr | head -1 | cut -d " " -f 1)
    
    lsof -l -n -p $pid > ~/`date "+%Y-%m-%d-%H%M"`.process.log 2>&1
    
    echo " "
    echo "$nameofprocess has $howmany files open, and is using $percent"%" of memory."
    echo "-----------------------------------"
    echo "A log has been created in your home directory"
    echo "-----------------------------------"
    echo " "
    echo ""$USER", do you want to terminate? (y/n)"
    read yn
    case $yn in
    
            [yY] | [yY][Ee][Ss] )
                    kill -15 $pid
                    ;;
    
            [nN] | [n|N][O|o] )
                    echo "Not killing. Powering down."
                    echo "......."
                    sleep 2
                    ;;
            *) echo "Does not compute"
                    ;;
    esac
    

2 个答案:

答案 0 :(得分:0)

您可以通过(更新)

实现此目的
#!/bin/bash

# place distribution independent code here
# dist=$(lsb_release -is)

if [[ -f /etc/redheat-release ]];
then # this is a RedHead based distribution like centos, fedora, ...
    dist="redhead"
elif [[ -f /etc/issue.net ]];
then
    # dist=$(cat /etc/issue.net | cut -d' ' -f1) # debian, ubuntu, ...
    dist="ubuntu"
else
    dist="unknown"
fi

if [[ $dist == "ubuntu" ]];
then
    # use your ubuntu command set
elif [[ $dist == "redhead" ]];
then
    # use your centos command set
else
    # do some magic here
fi

# place distribution independent code here

答案 1 :(得分:0)

这是我的脚本版本。它适用于Ubuntu和Debian。在某些方面它可能比你的更安全(当你的过程需要超过10%的内存时,我显然有一个错误,因为你的笨拙cut)。此外,您的ps不是“原子”,因此在ps的不同调用之间可能会发生变化。

#!/bin/bash

read percent pid nameofprocess < <(ps -eo pmem,pid,fname --sort=-pmem h)
mapfile -t openfiles < <(lsof -l -n -p $pid)
howmany=${#openfiles[@]}

printf '%s\n' "${openfiles[@]}" > ~/$(date "+%Y-%m-%d-%H%M.process.log")

cat <<EOF

$nameofprocess has $howmany files open, and is using $percent% of memory.
-----------------------------------
A log has been created in your home directory
-----------------------------------

EOF

read -p "$USER, do you want to terminate? (y/n) "

case $REPLY in
    [yY] | [yY][Ee][Ss] )
            kill -15 $pid
            ;;

    [nN] | [n|N][O|o] )
            echo "Not killing. Powering down."
            echo "......."
            sleep 2
            ;;
    *) echo "Does not compute"
            ;;
esac

首先,检查您的ps版本是否有--sort标记和h选项:

  • --sort=-pmem告诉pspmem
  • 减少进行排序
  • h告诉ps不显示任何标题

所有这一切都发送到read bash builtin,它读取空格分隔的字段,在这里显示字段pmempidfname并将这些值放入相应的变量percentpidnameofprocess

mapfile命令读取标准输入(此处为lsof命令的输出)并将每行放入数组字段中。该数组的大小由行howmany=${#openfiles[@]}计算。存储在数组lsof中的openfiles输出将输出到相应的文件。

然后,我们使用echo代替多个cat <<EOF,然后将read-p(提示)选项一起使用。

我不知道这是否真的回答了你的问题,但至少,你有一个编写良好的bash脚本,少了多次无用的命令调用(直到你的case语句,你调用了16个进程,我仅称为4)。此外,在第一次ps调用之后,脚本中的内容会发生变化(即使它不太可能发生),而不是在我的脚本中。

您可能还希望以下内容不会将lsof的输出放在数组中,而是使用额外的wc命令:

#!/bin/bash

read percent pid nameofprocess < <(ps -eo pmem,pid,fname --sort=-pmem h)
logfilename="~/$(date "+%Y-%m-%d-%H%M.process.log")
lsof -l -n -p $pid > "$logfilename"
howmany=$(wc -l < "$logfilename")

cat <<EOF

$nameofprocess has $howmany files open, and is using $percent% of memory.
-----------------------------------
A log has been created in your home directory ($logfilename)
-----------------------------------

EOF

read -p "$USER, do you want to terminate? (y/n) "

case $REPLY in
    [yY] | [yY][Ee][Ss] )
            kill -15 $pid
            ;;

    [nN] | [n|N][O|o] )
            echo "Not killing. Powering down."
            echo "......."
            sleep 2
            ;;
    *) echo "Does not compute"
            ;;
esac