Jex’s Note

Shell Script Examples

時間

DATE=`date +%Y-%m-%d`               // 2016-12-24
DATE=`date +%Y-%m-%d:%H:%M:%S`      // 2016-12-24:10:28:58

取得網卡 mac

pi@raspbmc:~$ ifconfig |awk '/eth/{print $1,$5}'
eth0 b8:27:eb:7e:6e:3f

測試複製(cp)速度

#!/bin/bash
begin=`date "+%s%N"`
cp /test/iso /test/qq/iso
end=`date "+%s%N"`
rel=$(($end-$begin))
echo $rel
  • 顯示結果為奈秒。
  • date "+%s%N" 為奈秒

shell script 判斷套件是否已安裝, 如果未安裝自動安裝(自動輸入yes)

if dpkg -s ${package} | grep -q installed; then
    echo "${package} installed"
else
    echo "${package} isn't installed."
    echo "Install ${package}.."
    sudo apt-get --force-yes --yes install ${package}
fi

取得 route IP (Gateway IP)

route -n | grep 'UG[ \t]' | awk '{print $2}'

or :

ip r | awk '/^def/{print $3}'

or :

netstat -rn |awk '{if($1=="0.0.0.0") print $2}'

檢查是否能上網

router_ip=$(netstat -rn |awk '{if($1=="0.0.0.0") print $2}')
ping -c1 ${router_ip} >> /dev/null 2>&1
if [ $? -eq 0 ]; then
    echo OK
else
    echo FAIL
fi

檢查 dns 是否運作正常

# Check DNS
set +e
echo "Check DNS ..."
function check_dns()
{
    is_successful=0
    for ((i=0; i<2; i++)); do
        host www.google.com > /dev/null 2>&1
        if [ $? -eq 0 ]; then
            is_successful=1
            break;
        else
            echo "DNS can't function ..."
            echo "Restart networking and check again ..."
            sudo service networking restart
        fi
    done
    return $is_successful
}
check_dns
if [ $? == 0 ]; then
    echo "DNS can't function ..."
    exit
fi
set -e

選擇 partition (private)

set +e
dev_array=(`echo $(sudo fdisk -l | grep -E '^\/dev\/sda([3-9]|\d{2})' | awk '{print $1}') | cut  -d " " --output-delimiter=" " -f 1-`)
dev_array_count=$((${#dev_array[@]}-1))
until [ "${xfs_choice_confirm}" == "y" ] || [ "${xfs_choice_confirm}" == "Y" ]
do
    df
    sudo fdisk -l
    echo -e "\nDevice list :"
    echo "----------------------"
    for ((i=0; i<=$dev_array_count; i++)); do
        printf " \E[0;33;40m${i}\E[0m : ${dev_array[$i]}\n"
    done
    echo "----------------------"
    printf "Please choose XFS partition by entering a number : "
    read  dev_choice
    echo "${dev_choice}" | grep -o "^[0-9]*$" >> /dev/null 2>&1
    if [ ! $? -eq 0 ] || [ -z ${dev_array[${dev_choice}]} ]; then
        continue
    fi
    printf "You choose \E[0;33;40m${dev_array[${dev_choice}]}\E[0m, are you sure \E[0;31;40m(y/n)\E[0m ? "
    read xfs_choice_confirm
done
xfs_partition=${dev_array[${dev_choice}]}
set -e

顯示資料夾下的檔案及空間

d.sh :

for x in `find /tmp/destination -type f | sort`
do
  sum_y=`sum $x`
  echo "$sum_y $x";
done

顯示結果

$ bash d.sh
34198    19 /tmp/destination/dd.php
63612     3 /tmp/destination/qq/fff/ffddxx.php
53866     2 /tmp/destination/qq/fff/pp.php
07572     1 /tmp/destination/qq/qq.php

第一列數字不清楚 第二列數字(19, 3, 2, 1)是換送成kb的容量

php syntax checking

#!/bin/bash

# For checking php and js syntax

if [ -z $1 ]; then
    echo
    echo "  ***Missing arguments"
    echo
    exit
fi
for PATH in $*
do
    reg=".*(\.php|\.js)"
    if [[ $PATH =~ $reg  ]]; then
        if [ ${BASH_REMATCH[1]} == ".php" ]; then
            printf "\33[0;35;44m$PATH : \33[0m\n"
            /usr/bin/php -l $PATH
            echo "-------------------"
        elif [ ${BASH_REMATCH[1]} == ".js" ]; then
            printf "\33[0;36;44m$PATH : \33[0m\n"
            /usr/bin/sudo -H -u $USER bash -c "$HOME/test_project/bin/jslint -f $PATH"
            echo "-------------------"
        fi
    fi
done

產生亂數字串

This method uses SHA to hash the date, runs through base64, and then outputs the top 32 characters.

jex@jex:~$ date +%s | sha256sum | base64 | head -c 32 ; echo
MmM1MWFjMDVhYzBkMzk3ODRjM2JiZTQ5

This method used the built-in /dev/urandom feature, and filters out only characters that you would normally use in a password. Then it outputs the top 32.

jex@jex:~$ < /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c${1:-32};echo;
udqgTdSRa_zWN1m6E_1iKMzCjvqXUUpD

This one uses openssl’s rand function, which may not be installed on your system. Good thing there’s lots of other examples, right?

jex@jex:~$ openssl rand -base64 32
39iFjCtPB+4zjjsdJJ+FtFjBYPD3GUDRIZtXld5UyRM=

This one works a lot like the other urandom one, but just does the work in reverse. Bash is very powerful!

jex@jex:~$ tr -cd '[:alnum:]' < /dev/urandom | fold -w30 | head -n1
Rz27w5YH3FF8D4ughqbgHkHIcgds9T

Here’s an even simpler version of the urandom one.

jex@jex:~$ < /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c6
RA0g58

You can even create a random left-hand password, which would let you type your password with one hand.

jex@jex:~$ </dev/urandom tr -dc '12345!@#$%qwertQWERTasdfgASDFGzxcvbZXCVB' | head -c8; echo ""
ZBFC@#AB

And here’s the easiest way to make a password from the command line, which works in Linux, Windows with Cygwin, and probably Mac OS X. I’m sure that some people will complain that it’s not as random as some of the other options, but honestly, it’s random enough if you’re going to be using the whole thing.

jex@jex:~$ date | md5sum
642a1b5de18a71b8585cfe87831d45a5  -

ref: random string

shell scripting and regular expression

echo "$password" | grep -q "[a-z]*[0-9][a-z]*"
if [ $? -eq 0 ] ;then
    echo "match found"
else
    echo "match not found"
fi
  • -q, –quiet, –silent
  • Quiet; do not write anything to standard output. Exit immediately with zero status if any match is found, even if
  • an error was detected. Also see the -s or –no-messages option. (-q is specified by POSIX.)

match $1

reg=".*(\.php)"
if [[ $PATH =~ $reg  ]]; then
    echo ${BASH_REMATCH[1]}
fi

input : t.php

result : .php

多行取代

sed "N;s/xxx/ccc/g" filename 因為加上 N 參數確實可以多行 matching, 但是當你要取代一個範圍(可能預期 match 到 3~6 行做取代) 卻是沒有辦法的..暈

那我將一個檔案讀取出來處理完再存到另一個檔案總沒問題了吧? 原則上是這樣沒錯..但是有一個小問題是行首的空白會不見.. 原來 bash shell 預設斷行是 space, tabs, new line(\n), 不過我們可以控制斷行的字元 - IFS(nternal Field Separator) 這個變數, 當 shell 內部讀取每一行時一遇到 \n 就中斷, 即可解決此問題, 請看以下程式碼 :

# 將檔案儲存到陣列
c=0
OLD_IFS=$IFS
IFS=$'\n'
while read -r line
do
    bashrcArray[$c]=$line
    c=$(expr $c + 1)
done < bashrc

# 這邊不做取代細節, 直接將陣列儲存成檔案
for i in "${bashrcArray[@]}"
do
    echo $i >> bashrcqq
done
IFS=$OLD_IFS
  • 注意 read 要加上 -r 參數, 否則反斜線(\)會被忽略
  • -r : If this option is given, backslash does not act as an escape character. The backslash is considered to be part of the line. In particular, a backslash-newline pair may not be used as a line continuation.

沒想到 shell script 處理多行取代居然會那麼麻煩

Comments