shell学习

shell学习

Shell 是一个命令解释权,它为用户提供了一个向 Linux 内核发送请求以便运行程序界面系统级程序,用户可以用 Shell 来启动、挂起、停止甚至是编写一些程序。

1、简单demo

进入 Linux 终端,编写一个 Shell 脚本 hello.sh :

#!/bin/bash 
echo 'hello world!'

运行

# 方法1 
sh hello.sh  

# 方法2 
chmod +x hello.sh 
./hello.sh

说明

#! 告诉系统这个脚本需要什么解释器来执行。
文件扩展名 .sh 不是强制要求的。
方法1 直接运行解释器,hello.sh 作为 Shell 解释器的参数。此时 Shell 脚本就不需要指定解释器信息,第一行可以去掉。
方法2 hello.sh 作为可执行程序运行,Shell 脚本第一行一定要指定解释器。

2、shell中的变量

Shell 变量分为系统变量自定义变量。系统变量有$HOME、$PWD、$USER等。

显示当前 Shell 中所有变量,直接在命令窗口输入命令:set

变量名可以由字母、数字、下划线组成,不能以数字开头。

基本语法

  • 定义变量:变量名=变量值,等号两侧不能有空格,变量名一般习惯用大写。

  • 删除变量:unset 变量名 。

  • 声明静态变量:readonly 变量名,静态变量不能unset。

  • 使用变量:$变量名

  • 将命令返回值赋给变量

    A=`ls` #反引号,执行里面的命令
    A=$(ls) #等价于反引号
    

设置环境变量

  • export 变量名=变量值,将 Shell 变量输出为环境变量。

    vi /etc/profile
    在文件后面追加:
    export CESHI=ceshi
    
  • source 配置文件路径,让修改后的配置信息立即生效。

    source /etc/profile
    
  • echo $变量名,检查环境变量是否生效

位置参数变量

  • $n :$0 代表命令本身、$1-$9 代表第1到9个参数,10以上参数用花括号,如 ${10}。

  • $* :命令行中所有参数,且把所有参数看成一个整体。

  • $@ :命令行中所有参数,且把每个参数区分对待。

  • $# :所有参数个数。

  • demo

    #编写 Shell 脚本 positionParam.sh:
    #!/bin/bash     
    # 输出各个参数 
    echo $0 $1 $2 
    echo $* 
    echo $@ 
    echo 参数个数=$#
    执行shell
    chmod +x positionParam.sh 
    ./positionParam.sh 10 20
    执行结果
    ./positionParam.sh 10 20 
    10 20 
    10 20 
    参数个数=2
    

预定义变量

在 Shell 脚本中直接引用的变量,默认值

  • $$ :当前进程的 PID 进程号。

  • $! :后台运行的最后一个进程的 PID 进程号。

  • $? :最后一次执行的命令的返回状态,0为执行正确,非0执行失败。

  • demo

    编写 Shell 脚本 preParam.sh
    vi preParam.sh 内容如下:
    #!/bin/bash     
    echo 当前的进程号=$$ 
    # &:以后台的方式运行程序 
    ./hello.sh & 
    echo 最后一个进程的进程号=$! 
    echo 最后执行的命令结果=$?
    运行结果:
    当前进程号=2234
    最后一个进程的进程号2235
    最后的命令执行结果0 # hello.sh的输出
    

3、运算符

  • $((运算式)) 或 $[运算式]

  • expr m + n 注意 expr 运算符间要有空格

  • expr m - n

  • expr *,/,% 分别代表乘,除,取余

  • demo

    # 第1种方式 $(()) 
    echo $(((2+3)*4))   
    
    # 第2种方式 $[],推荐 
    echo $[(2+3)*4]  
    
    # 使用 expr 
    TEMP=`expr 2 + 3` 
    echo `expr $TEMP * 4`
    

4、流程控制

if判断

[ condition ] 注意condition前后要有空格。非空返回0,0为 true,否则为 false 。

demo1:

#!/bin/bash 
if [ 'test01' = 'test' ] 
then
     echo '等于' 
fi  

# 20是否大于10 
if [ 20 -gt 10] 
then
     echo '大于' 
fi  

# 是否存在文件/root/shell/a.txt 
if [ -e /root/shell/a.txt ] 
then
     echo '存在' 
fi  

if [ 'test02' = 'test02' ] && echo 'hello' || echo 'world' 
then
     echo '条件满足,执行后面的语句' 
fi

执行结果:
大于 
hello 
条件满足,执行后面的语句

demo2:

#!/bin/bash
if [ $1 -ge 60 ]
then
    echo 及格
elif [ $1 -lt 60 ]
then
    echo "不及格" 
fi

case分支

demo

case $1 in
"1")
echo 周一
;;
"2")
echo 周二
;;
*)
echo 其它
;;
esac

for循环

基本语法

# 语法1
for 变量名 in 值1 值2 值3...
do
    程序
done

# 语法2
for ((初始值;循环控制条件;变量变化))
do
    程序
done

demo1

#!/bin/bash  

# 使用$* 
for i in "$*" 
do     
    echo "the arg is $i" 
done 
echo "=================="  

# 使用$@ 
for j in "$@" 
do     
    echo "the arg is $j" 
done
执行结果:
the arg is 1 2 3 
================== 
the arg is 1 
the arg is 2 
the arg is 3

demo2

#!/bin/bash 
SUM=0  
for ((i=1;i<=100;i++)) 
do     
    SUM=$[$SUM+$i] 
done 

echo $SUM

while循环

语法

while [ 条件判断式 ]
do
    程序
done 

demo

#!/bin/bash
SUM=0
i=0

while [ $i -le $1 ]
do
    SUM=$[$SUM+$i]
    i=$[$i+1]
done       
echo $SUM

5、读取控制台输入

基本语法

read(选项)(参数)

-p:指定读取值时的提示符
-t:指定读取值时等待的时间(秒),如果没有在指定时间内输入,就不再等待了。
变量名:读取值的变量名

demo

#!/bin/bash

read -p "请输入一个数num1=" NUM1
echo "你输入num1的值是:$NUM1"

read -t 10 -p "请在10秒内输入一个数num2=" NUM2
echo "你输入num2的值是:$NUM2"
输出:
请输入一个数num1=10
你输入num1的值是:10
请在10秒内输入一个数num2=20
你输入num2的值是:20

6、函数

和其它编程语言一样,Shell 编程有系统函数和自定义函数

系统函数

  • basename 删掉路径最后一个 / 前的所有部分(包括/),常用于获取文件名

    basename [pathname] [suffx]
    basename [string] [suffx]
    如果指定 suffx,也会删掉pathname或string的后缀部分
    
  • dirname 删掉路径最后一个 / 后的所有部分(包括/),常用于获取文件路径

    dirname pathname
    如果路径中不含 / ,则返回 '.' (当前路径)
    

自定义函数

语法

[ function ] funname[()]
{
    Action;
    [return int;]
}

# 调用
funname 参数1 参数2...

demo

#!/bin/bash

function getSum(){
    SUM=$[$n1+$n2]
    echo "函数打印: $SUM"
    return $SUM
}

read -p "请输入第一个参数n1:" n1
read -p "请输入第二个参数n2:" n2

# 调用 getSum 函数
getSum $n1 $n2
echo "结果打印:$?"

7、一份完整的java程序脚本

#!/bin/bash
#
# description: {{ APPID }} init script
# processname: tomcat  
# chkconfig: 234 20 80 

APPID="AppPurchaseService"
USER="deploy"

### paths
PROJECT_DIR=/workspace/carkey/AppPurchaseService/latest/
PROJECT_LOG=/workspace/carkey/AppPurchaseService/
MAIN_CLASS="com.hellobike.platform.aps.deploy.Application"
START_OPTS="$START_OPTS -DAPPID=$APPID"

cd ${PROJECT_DIR}

#Memory configs
MEM_OPTS="-Xms5120m -Xmx5120m -Xmn1706m -XX:MaxMetaspaceSize=512m -XX:MetaspaceSize=512m"

#GC OPTS
GC_OPTS="$GC_OPTS -XX:+UseConcMarkSweepGC 
-XX:+UseParNewGC 
-XX:+UseCMSCompactAtFullCollection 
-XX:CMSFullGCsBeforeCompaction=0 
-XX:CMSInitiatingOccupancyFraction=62 
-XX:CMSTriggerRatio=70"

#GC logging
GC_OPTS="$GC_OPTS -Xloggc:${PROJECT_LOG}/logs/gc.log"
GC_OPTS="$GC_OPTS -XX:+PrintGCDateStamps -XX:+PrintGCDetails"
GC_OPTS="$GC_OPTS -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=${PROJECT_LOG}/logs/heapdump.hprof"

# JMX OPTS
JMX_OPTS="$JMX_OPTS -Dcom.sun.management.jmxremote.port=15005 
-Dcom.sun.management.jmxremote.authenticate=false 
-Dcom.sun.management.jmxremote.ssl=false 
-Dcom.sun.management.jmxremote=true 
-Dowl.metrics.kafka.servers=owl.kafka1.ttbike.com.cn:9092,owl.kafka2.ttbike.com.cn:9092,owl.kafka3.ttbike.com.cn:9092"


START_OPTS="$START_OPTS -Djava.io.tmpdir=$PROJECT_DIR/temp/"
START_OPTS="$START_OPTS -Duser.dir=$PROJECT_DIR"

CLASS_PATH="$PROJECT_DIR/conf:$PROJECT_DIR/lib/*:$CLASS_PATH"


# get pid
getPid(){
    if [ -z $1 ]
    then
        echo "Usage: $0 process-pattern" >&2
        exit 1
    fi

    exc_pids="^$$$"
    curr_pid=$$
    while [ $curr_pid -gt 0 ]
    do
        curr_pid=`ps -fwwp $curr_pid|grep -v PPID|awk '{print $3}'`
        exc_pids="$exc_pids|^$curr_pid$"
    done
    curr_script=$0
    curr_script=${curr_script#.}
    curr_script=${curr_script//./\.}

    if [ $# -eq 1 ]
    then
        ps -efww|grep "$1"|grep '-DAPPID='|grep -Ev "grep|$curr_script"|awk '{print $2}'|grep -Ev $exc_pids
    else
        firstArg=$1
        shift
        ps -efww|grep "$firstArg "|grep "$*"|grep '-DAPPID='|grep -Ev "grep|$curr_script"|awk '{print $2}'|grep -Ev $exc_pids
    fi
}

#return value
retval=0
getNameFromPid(){
   nowTime1=$(date)
   tips="冲突时间"
   printf "冲突进程信息请查看:/tmp/startCrash.log
"

   echo $tips$nowTime1 >> /tmp/startCrash.log
   echo "冲突进程数量:" $# >> /tmp/startCrash.log

   for loop in $*
   do
       ps -ef|grep $loop|grep -v grep >> /tmp/startCrash.log
   done
}
# start the server
start(){
    printf 'Starting the server
'
    pids=`getPid $APPID`
    if ! [ -z "$pids" ];then
        printf 'Existing process: %d
' "$pids"
        getNameFromPid $pids
        retval=1
    else
        #start
        mkdir -p "$PROJECT_DIR/temp/"
        mkdir -p "$PROJECT_DIR/logs/"
        #echo "MEM_OPTS: $MEM_OPTS"
        #echo "GC_OPTS: $GC_OPTS"
        #echo "JMX_OPTS: $JMX_OPTS"
        #echo "START_OPTS: $START_OPTS"
         chown -R deploy.deploy $PROJECT_LOG/
         chown -R deploy.deploy $PROJECT_DIR/
         chown -R deploy.deploy $PROJECT_LOG/logs/
        JAVA_CMD="nohup java -server $MEM_OPTS $GC_OPTS $JMX_OPTS $START_OPTS -Denv=pro -DAPPID=AppPurchaseService -Dfile.encoding=UTF-8 -classpath $CLASS_PATH $MAIN_CLASS $PROJECT_DIR/conf/Configure.json > $PROJECT_LOG/logs/jvm_std.log 2>&1 &"
        echo $JAVA_CMD
        if ! [ `whoami` = "deploy" ];then
          /bin/su $USER -c "mkdir -p $PROJECT_DIR/temp/"
          /bin/su $USER -c "$JAVA_CMD"
        else
          mkdir -p $PROJECT_DIR"/temp/"
          /bin/bash -c "$JAVA_CMD"
        fi
        echo "Process pid: `getPid $APPID`"
        sleep 3
        if [ -z `getPid $APPID` ]
        then
            echo "Failed to start the server"
            retval=1
        else
            echo "Finish $0"
            retval=0
        fi
    fi
}

# stop the server
stop(){
    printf 'Stopping the server
'
    pids=`getPid $APPID`
    if [ -z "$pids" ]
    then
        printf 'process is not running
'
        retval=0
    else
        #stop
        max_loop=10
        for ((i=0; i<$max_loop; i++))
        do
            pids=`getPid $APPID`
            if [ -z "$pids" ]
            then
                break;
            fi

            if [ $i -gt 5 ]
            then
                _9="-9"
            fi

            for pid in $pids
            do
                echo "Kill process with pid:$pid and pattern:$MAIN_CLASS"
                if ! kill $_9 $pid
                then
                    echo "Failed kill process with pid:$pid and pattern:$MAIN_CLASS"
                else
                    echo "Succeed kill process with pid:$pid and pattern:$MAIN_CLASS"
                fi
            done

            sleep 3
        done

        if [ $i -eq $max_loop ]
        then
            echo_t "Failed kill the processes $pids after try $max_loop times"
            retval=1
        else
            retval=0
        fi
    fi
}

# status for server
status(){
    pids=`getPid $APPID`
    if ! [ -z "$pids" ];then
        printf 'server is running: %d
' "$pids"
    else
        printf 'server is stopped
'
    fi
}

user_exists(){
        if id -u $1 >/dev/null 2>&1; then
        echo "1"
        else
                echo "0"
        fi
}

# dispatch the command
case "$1" in
    start)
    start
    ;;
    stop)
    stop
    ;;
    status)
    status
    ;;
    restart)
    stop
    start
    ;;
    *)
    printf 'Usage: %s {start|stop|restart|status}
'
    exit 1
    ;;
esac


# exit
exit "$retval"



# END OF FILE
原文地址:https://www.cnblogs.com/hhhshct/p/14320905.html