標籤:linux shell 設定檔 容錯
不久以前,曾經搜到一篇部落格是讀取設定檔的,http://www.cnblogs.com/bo083/archive/2012/11/19/2777076.html,用到現在,感覺十分方便,感謝作者。
現在,需要通過web介面給使用者留出介面來修改類似設定檔,大的方法是從php調用linux shell script,於是,現在貼一個可以修改此種設定檔的linux shell。
首先,設定檔的格式如下:
[unit1]field1=value1field2=value2[unit2]field1=value3field3=value4......
例子如下,config.ini:
[DATABASE]dbms_ip=localhostuser=rootpasswd=clouddb_name=cloudport=2394[BUSINESS]port=9084[OFFLINE]pcap_file=test.pcap
設定檔中包含3個unit,表示3個大的方面:資料庫,業務,離線;每個unit有屬於自己的欄位名及欄位值。
上文中引用部落格正是能讀取這樣的設定檔,而目前我們便是要通過linux shell來修改這個設定檔。
我們設計的程式名為 modify_config_file,使用 ./modify_config_file unit1-field1=changed_value1 unit2-field1=changed_value2 這樣的格式(參數可以繼續添加)來進行修改。
要做到修改設定檔的功能其實並不難,20-30行便可以解決問題。但是基於“一切輸入都是有害的”的原則,需要在shell中加入各種容錯處理,如果使用者參數輸入錯誤,要能及時提醒使用者,定位問題所在,下面是基於這樣一個初衷的shell,當然,名稱為modify_config_file:
#!/bin/bashPATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbinexport PATH#Program#This program is to modify the configuration file #History#2014.10.30 WeiZheng 1.1MY_HOME="/home/weizheng/10-30-yg/yg-soft"CONFIG_FILE="$MY_HOME/config.ini"ERROR_NUM=255function get_line_num(){# Check if the argument name has the separator "-" that separate the argument unit and argument fieldseparator=$(echo $1 | grep "-")if [ -z "$separator" ]; thenecho -e "error: \"$1\": argument name has no separator \"-\" that separate the argument unit and argument field"exit $ERROR_NUMfi# Check if the argument name has argument unit and argument fieldarg_unit=$(echo $1 | cut -d "-" -f 1)arg_field=$(echo $1 | cut -d "-" -f 2)if [ -z "$arg_unit" -o -z "$arg_field" ]; thenecho -e "error: \"$1\": argument name has no argument unit or argument field around \"-\""exit $ERROR_NUMfi# Get the argument unit's interval [$arg_unit_line_num, $next_neighbour_unit_line_num)arg_unit_line_num=$(grep -n "\[$arg_unit\]" $CONFIG_FILE | cut -d ":" -f1)if [ -z "$arg_unit_line_num" ]; thenecho -e "error: \"$arg_unit\": can not find argument unit"exit $ERROR_NUMfinext_neighbour_unit_line_num=$(awk "NR>$arg_unit_line_num && /^\[.*\]/ {print NR; exit 0}" $CONFIG_FILE)if [ -z "$next_neighbour_unit_line_num" ]; thenfile_line_count=$(wc -l $CONFIG_FILE | cut -d " " -f 1)next_neighbour_unit_line_num=$((file_line_count+1))fiecho "argument unit interval: ($arg_unit_line_num, $next_neighbour_unit_line_num)"arg_field_line_nums=$(grep -n "^$arg_field=" $CONFIG_FILE | cut -d ":" -f1 | tr "\n" "\ ")if [ -z "$arg_field_line_nums" ]; thenecho -e "error: \"$arg_field\": can not find argument field"exit $ERROR_NUMfiecho "matched argument field in line: $arg_field_line_nums"# the $arg_field_line_num must in the interval ($arg_unit_line_num, $next_neighbour_unit_line_num)for arg_field_line_num in $arg_field_line_numsdoif [ $arg_field_line_num -gt $arg_unit_line_num -a $arg_field_line_num -lt $next_neighbour_unit_line_num ]; thenecho "find argument field in line: $arg_field_line_num"return $arg_field_line_numfidone# if not return in for-loop, the arg_field_line_num is not in the interval ($arg_unit_line_num, $next_neighbour_unit_line_num)echo -e "the argument field is not in the argument unit interval"exit $ERROR_NUM}while [ "$1" ]do# Check if the separator "=" that separate the argument name and argument value existsequal_symbol=$(echo $1 | grep "=")if [ -z "$equal_symbol" ]; thenecho -e "error: \"$1\": argument has no \"=\""exit $ERROR_NUMfi# Check if argument name and argument value existarg_name=$(echo $1 | cut -d "=" -f 1)arg_value=$(echo $1 | cut -d "=" -f 2)if [ -z "$arg_name" -o -z "$arg_value" ]; thenecho -e "error: \"$1\": argument has no name or value around \"=\""exit $ERROR_NUMfi# Get the line number of the argument from CONFIG_FILEget_line_num $arg_nameargs_line_num=$?# use sed change the argument linearg_field=$(echo $arg_name | cut -d "-" -f 2)sed -i "${args_line_num}c $arg_field=$arg_value" $CONFIG_FILEnew_line=$(sed -n "${args_line_num}p" $CONFIG_FILE)echo "the argument has been changed: $new_line"shift 1done
使用者通過以下命令修改配置:
./modify_config_file BUSINESS-port=8888
輸出如下:
argument unit interval: (8, 11)matched argument field in line: 6 9 find argument field in line: 9the argument has been changed: port=8888
其中,第一行表示找到BUSINESS這個unit所在的行號區間,注意是開區間;第二行表示所有匹配到field行號,因為可能多個unit中有相同的field;第三行表示最終落入unit區間的field行號;第四行表示所在行修改後的結果。
另外,使用者輸入不符合格式是很有可能,針對以下幾種錯誤都會報告並且定位:
1. ./modify_config_file BUSINESSerror: "BUSINESS": argument has no "="2. ./modify_config_file BUSINESS=error: "BUSINESS=": argument has no name or value around "="3. ./modify_config_file BUSINESS=8888error: "BUSINESS": argument name has no separator "-" that separate the argument unit and argument field4. ./modify_config_file BUSINESS-=8888error: "BUSINESS-": argument name has no argument unit or argument field around "-"5. ./modify_config_file BUSINESS-por=8888argument unit interval: (8, 11)error: "por": can not find argument field6. ./modify_config_file BUSINE-port=8888error: "BUSINE": can not find argument unit
如果要應用到其它的設定檔,需要在指令碼中修改設定檔所在路徑與檔案名稱:
MY_HOME="/home/weizheng/10-30-yg/yg-soft"CONFIG_FILE="$MY_HOME/config.ini"
一個修改設定檔的linux shell script