shell的GoodCoder的编写
来源:互联网 发布:golang defer func 编辑:程序博客网 时间:2024/04/19 09:46
runit是一个应用(application)启动管理工具。通过Procfile文件启动相应的进程。
1 试题描述
1.1 Procfile
Procfile 包含进程名字和启动进程的命令,用:分隔。如:
web: python -m SimpleHTTPServer $PORTdate: date $DATE_FORMATweb_2: while true ; do nc -l $PORT < index.html
- 进程名字可以包含:字母, 数字, 下划线
- Procfile中不可以写后台命令
- runit将这些命令运行在后台
- runit默认使用当前路径下的Procfile文件
- 如果多次使用$PORT变量,则值递增。如第一个PORT的值是8080,则第二个PORT的值为8081,如果不在.env中设置PORT变量的值,则自动设置默认值为8080
1.2 环境变量
如果当前目录下存在.env文件,则从其中读取环境变量。这个文件由 键/值对 构成。如:
PORT=8080DATE_FORMAT='+%Y-%m-%d|%H:%M:%S'
1.3 程序执行
- runit 启动Procfile中的所有进程
- runit -f procfile -e env_file
- runit -c 检查Procfile, env_file文件格式的正确性
- runit -h 打印帮助
1.4 其他要求
- Procfile和.env文件中可存在#注释
- usage内容第一行如下, 其余内容自由发挥
Usage: runit [-c] [-f procfile|Procfile] [-e envfile|.env]
- 日志打印到屏幕,格式如下,不同的进程的日志输出不同的颜色(web, date, web_2分别是不同的颜色)
11:39:45 web | python -m SimpleHTTPServer 8080 started with pid 78111:39:45 date | date +%Y-%m-%d|%H:%M:%S started with pid 79011:39:45 web_2 | nc -l 8081 < index.html started with pid 801
- runit按照Procfile的描述启动进程,例如web就是启动一个前台进程(非后台进程或daemon)
- runit可以接收SIGINT和SIGTERM信号,杀掉已启动的进程。确保runit在子进程运行结束后才退出。(如果进程可瞬间完成或是后台进程,则这个功能不起作用)
- 除grep外不允许使用其他外部命令,如:sed, awk, ps, bc
- 遵循shell编程规范
二、代码展示
#!/bin/bash##Copyright (c) 2016 Baidu.com,Inc. All Right Reserved##Author:panlu@baidu.com#Date:2016/08/17##Brief:# process launcher#Globals:# PORT COLOR_ARRAY#Arguments:# -c check# -f procfile# -e envfile# -h help#Returns:# succ:0# fail:1set -o pipefail# environmentSPORT=8080COLOR_ARRAY=('32' '33' '34' '35' '36')# variableprocfile=""envfile=""######################################Brief:# usage#Globals:# none#Agruments:# none#Returns:# none#####################################function usage() { echo "Usage: runit [-c] [-f procfile|Procfile] [-e envfile|.env] -c: check procfile and envfile -f: load the procfile -e: load the envfile -h: help information "}######################################Brief:# verify the envfile#Globals:# none#Agruments:# envfile#Returns:# succ:0# fail:1#####################################function verify_env() { local env_file="$1" local ret_val=0 [[ ! -f "${env_file}" ]] && my_err "verify envfile not exists" && return 1 while read nextline; do if echo "${nextline}" | grep -v "="; then my_err "no_equal_mark" continue fi key="${nextline%%=*}" value="${nextline#*=}" echo "${key}" | grep -q "[^a-zA-Z_]" && my_err "invalid_char" && ret_val=1 echo "${value}" | grep -qE "[[:space:]]" && my_err "value_have_space" && ret_val=1 done < <(grep -vE "^[[:space:]]*#" "${env_file}" | grep -v "^$") return ${ret_val}}######################################Brief:# verify the procfile#Globals:# none#Agruments:# procfile#Returns:# succ:0# fail:1#####################################function verify_proc() { local proc_file="$1" local ret_val=0 [[ ! -f "${proc_file}" ]] && my_err "verify procfile not exists" && return 1 while read nextline ; do if echo "${nextline}" | grep -v ":"; then my_err "no_colon_command" continue fi key="${nextline%%:*}" value="${nextline#*:}" echo "${key}" | grep -q [^a-zA-Z_] && my_err "invalid_char" && ret_val=1 done < <(grep -vE "^[[:space:]]*#" "${proc_file}") return ${ret_val}}######################################Brief:# echo the error information#Globals:# none#Agruments:# errinfo#Returns:# none#####################################function my_err() { errinfo="$1" echo "${errinfo}"}######################################Brief:# echo the log information#Globals:# COLOR_ARRAY #Agruments:# proc_name command#Returns:# succ:0# fail:1#####################################function log() { local name="$1" local command="$2" local color="$3" cur_time=$(date +%H:%M:%s) printf "\E[${color}m${cur_time} %-7s] | " "${name}" tput sgr0 echo "${command}" return 0}######################################Brief:# execute the command#Globals:# COLOR_ARRAY PORT#Agruments:# proc_name command#Returns:# succ:0# fail:1#####################################function run_command() { local number="1" local proc_name="$1" local command="$2" local cur_pid=$! local cur_color="${COLOR_ARRAY[$number]}" local comm_port=$(echo "${command}" | grep -e "\$PORT") [[ -n "${comm_port}" ]] && [[ -z "${PORT}" ]] && PORT=8080 bash -c "${command}" > >( while read result; do log "${proc_name}" "${result}" "${COLOR}" done ) 2>&1 & local output="$(eval echo \"${command}\")" log "${proc_name}" "${output} start with pid ${cur_pid}" "${cur_color}" [[ $? -ne 0 ]] && return 1 [[ -n "${comm_port}" ]] && PORT=$((${PORT} + 1)) (( number ++ )) return 0}######################################Brief:# load the env_file#Globals:# none#Agruments:# envfile#Returns:# succ:0# fail:1#####################################function load_env_file() { set -a local env_lists="$1" for flag in $(echo "${env_lists}"); do [[ -f "${flag}" ]] && source "${flag}" done return 0}######################################Brief:# run procfile#Globals:# none#Agruments:# procfile#Returns:# succ:0# fail:1#####################################function run_procfile() { local proc_file="$1" [[ ! -f "${proc_file}" ]] && my_err "this procfile is not exists" && return 1 while read nextline; do if echo "${nextline}" | grep -qv ":"; then my_err "no_colon_command" continue fi local key="${nextline%%:*}" local value="${nextline#*:}" [[ -n "${key}" ]] && [[ -n "${value}" ]] && run_command "${key}" "${value}" [[ $? -ne 0 ]] && return 1 done < <(grep "" "${proc_file}" | grep -vE "[[:space:]]*#" | grep -v "^$" ) wait return 0}######################################Brief:# main procedure#Globals:# procfile encfile#Agruments:# none#Returns:# none#####################################function main() { local check=false while getopts "f:e:ch" flag do case ${flag} in c) check=true ;; f) procfile="${OPTARG}" ;; e) envfile="${OPTARG}" ;; *) usage ;; esac done if ${check}; then if [[ -n "${procfile}" ]]; then verify_proc "${procfile}" PROC_RET_VALUE=$? [[ ${PROC_RET_VALUE} -ne 0 ]] && exit 1 else my_err "The procfile is null" exit 1 fi if [[ -z "${envfile}" ]];then envfile="./.env" fi verify_env "${envfile}" ENV_RET_VALUE=$? [[ ${ENV_RET_VALUE} -ne 0 ]] && exit 1 else if [[ -z "${envfile}" ]]; then envfile="./.env" fi load_env_file "${envfile}" LOAD_ENV_RET_VALUE=$? [[ ${LOAD_ENV_RET_VALUE} -ne 0 ]] && exit 1 if [[ -z "${procfile}" ]]; then procfile="./Procfile" fi run_procfile "${procfile}" RUN_RET_VALUE=$? [[ RUN_RET_VALUE -ne 0 ]] && exit 1 fi exit 0} main "$@"
0 0
- shell的GoodCoder的编写
- shell脚本的编写
- shell脚本的编写
- shell脚本的编写
- 简单shell的编写
- shell进度条的编写
- shell 脚本 与 shell 脚本的编写
- 关于 Shell Code 的编写
- 嵌入式Linux的Shell编写
- shell编写的垃圾回收站
- linux shell脚本的编写
- 编写自己的shell(3)
- Shell编写脚本的笔记
- 自己编写简单的shell
- linux 编写自己的shell
- shell脚本编写的flipbird
- 编写简单的shell脚本
- 自己编写的简单shell
- SDUT OJ 3362 数据结构实验之图论六:村村通公路
- 排列
- PHP 底层的运行机制与原理
- 解决Vim/Gvim插入模式下backspace按键无法删除字符的问题
- 简单易学的机器学习算法——极限学习机(ELM)
- shell的GoodCoder的编写
- 总结
- 四、用文件对数据进行存储
- Python学习笔记--DataFrame使用
- ZZULI 1917: E
- 位运算入门应用以及技巧
- 【BZOJ1013】球形空间产生器,第一次的高斯消元
- 五、Android的assets资源使用
- java经典问题生兔子