您的位置:

提高Shell脚本的可读性和可维护性的方法

Shell脚本是一种强大的脚本语言,被广泛地用于自动化任务,产品部署等领域,在实践中,我们不仅需要让脚本执行正确,还要让别人阅读脚本时不会头疼,这就需要Shell脚本有比环境变量更好的可读性和可维护性。

一、编写注释

注释是提高Shell脚本可读性和可维护性的最佳方式之一。无论是在脚本中调用的每个函数、变量,还是在声明变量和函数的地方,都应该编写注释说明其功能。例如:

#!/bin/bash

# This script is used to create Jenkins jobs.

# Declare global variables.
JENKINS_HOME="/usr/local/jenkins"
JOB_DIR=$JENKINS_HOME/jobs

# Declare function to create jobs.
function create_jobs() {
    # This function is used to create Jenkins jobs.
    for file in $JOB_DIR/*.xml
    do
        # Check if file exists.
        if [ -f $file ]; then
            # Create the job based on the XML file.
            curl -X POST -H "Content-Type:application/xml" -d "@$file" "http://localhost:8080/createItem?name=${file%%.*}"
        fi
    done
}

create_jobs

在此示例中,注释用于说明脚本的用途、全局变量以及功能函数的用途。

二、使用函数

将代码分解为小块的函数会增强Shell脚本的可读性。函数也使得Shell脚本的逻辑更加清晰,易于维护。例如:

#!/bin/bash

# This script is used to backup files to remote server.

# Declare global variables.
REMOTE_USER="user"
REMOTE_IP="192.168.1.100"
REMOTE_PATH="/data/backup"
LOCAL_DIR="/data/backup"
FILES="*.tar.gz"

# Declare function to backup files to remote server.
function backup_files() {
    # This function is used to backup files to remote server.
    scp $LOCAL_DIR/$FILES $REMOTE_USER@$REMOTE_IP:$REMOTE_PATH
}

# Declare function to compress files.
function compress_files() {
    # This function is used to compress files.
    tar -zcvf $LOCAL_DIR/backup-$(date +%Y-%m-%d).tar.gz $LOCAL_DIR/$FILES
}

compress_files
backup_files

在此示例中,我们将脚本分解为两个函数:compress_files()和backup_files()。这样可以为脚本增加逻辑清晰度和可读性。

三、使用环境变量

为可重用的方式定义环境变量是一种增强Shell脚本可读性和可维护性的方法。例如:

#!/bin/bash

# This script is used to install MySQL.

# Declare global variables.
MYSQL_VERSION="5.7.30"
MYSQL_DOWNLOAD_URL="https://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-$MYSQL_VERSION-linux-glibc2.12-x86_64.tar.gz"

# Declare function to install MySQL.
function install_mysql() {
    # This function is used to install MySQL.
    wget $MYSQL_DOWNLOAD_URL
    tar -xvf mysql-$MYSQL_VERSION-linux-glibc2.12-x86_64.tar.gz
    mkdir /usr/local/mysql
    mv mysql-$MYSQL_VERSION-linux-glibc2.12-x86_64/* /usr/local/mysql/
    echo "export PATH=$PATH:/usr/local/mysql/bin" >> /etc/profile
    source /etc/profile
    mysql_install_db
}

install_mysql

在此示例中,我们定义了MYSQL_VERSION和MYSQL_DOWNLOAD_URL环境变量,这使我们能够轻松地更改下载URL和版本。可以通过更改环境变量值,很方便地修改脚本。

四、使用函数库

使用Shell函数库可以增强脚本的可读性,可重用性以及可维护性。例如:

#!/bin/bash

# This script is used to backup MongoDB database.

# Import function library.
source backup_functions.sh

# Declare global variables.
MONGO_DB="test"
BACKUP_DIR="/data/backup/mongo"
DATE=$(date +%Y-%m-%d)

# Create directory for backup file.
mkdir -p $BACKUP_DIR

# Backup MongoDB.
backup_mongo $MONGO_DB $BACKUP_DIR $DATE

在此示例中,我们导入了backup_functions.sh中的函数库,并使用backup_mongo()函数备份MongoDB数据库。

backup_functions.sh

#!/bin/bash

# Declare function to backup MongoDB.
function backup_mongo() {
    # This function is used to backup MongoDB database.
    local db_name=$1
    local backup_dir=$2
    local date=$3
    
    mongodump -d $db_name -o $backup_dir/$date
    tar -zcvf $backup_dir/$date.tar.gz $backup_dir/$date
    rm -rf $backup_dir/$date
}

在backup_functions.sh中,我们定义了backup_mongo()函数,用于备份MongoDB数据库,该函数实现了备份MongoDB、压缩备份文件和删除临时备份文件三个功能,这样脚本变得更加灵活,扩展性更强。

五、使用配置文件

使用配置文件可以增强Shell脚本的灵活性和可维护性。例如:

#!/bin/bash

# Import configuration file.
source backup.conf

# Declare function to backup files to remote server.
function backup_files() {
    # This function is used to backup files to remote server.
    scp $LOCAL_DIR/$FILES $REMOTE_USER@$REMOTE_IP:$REMOTE_PATH
}

backup_files

backup.conf

# This is the configuration file for backup.sh.

REMOTE_USER="user"
REMOTE_IP="192.168.1.100"
REMOTE_PATH="/data/backup"
LOCAL_DIR="/data/backup"
FILES="*.tar.gz"

在此示例中,我们将配置信息存储在backup.conf文件中,然后从脚本中导入该文件。这样我们就可以轻松地更改配置信息而不必修改脚本。例如,我们可以更改REMOTE_USER而不必直接修改脚本。

结论

在日常工作中,提高Shell脚本可读性和可维护性是至关重要的。编写注释,使用函数,环境变量和函数库,使用配置文件等方法都可以增强Shell脚本的可读性和可维护性。

提高Shell脚本的可读性和可维护性的方法

2023-05-13
提高Python代码的可读性和可维护性的方法

2023-05-13
用Swagger提高API文档可读性和可维护性的方法

2023-05-18
Linux运维工程师必备的Shell脚本格式

2023-05-13
Linux运维工程师必备的Shell脚本技巧

2023-05-13
编写高效的Linux运维脚本,提升工作效率

2023-05-13
Linux运维工程师必备的Shell脚本命令

2023-05-13
Java特性:提高代码可读性、可维护性和可扩展性

2023-05-17
Java代码规范:提高代码可读性和可维护性的实践方法

2023-05-18
使用C++引用提高代码可读性和可维护性

2023-05-13
Python注释:提高代码可读性和可维护性

2023-05-13
Shell-F:Linux运维必备的快速脚本编写工具

2023-05-13
C++注释:提高代码可读性和可维护性的技巧

2023-05-13
Linux Shell脚本的基础语法和使用方法

2023-05-13
Shell脚本编程:实现Linux自动化运维管理

2023-05-13
Linux运维工程师必备技能:Shell++脚本编程

2023-05-12
Shell脚本开头详解

2023-05-18
基于Linux的Shell脚本实现自动化任务管理

2023-05-12
Linux运维:理解Bash脚本和Shell脚本的不同用途

2023-05-13
when-present<#else>when-missing. (These only cover the last step of the expression; to cover the whole expression, use parenthesis: (myOptionalVar.foo)!myDefault, (myOptionalVar.foo)?? ---- ---- FTL stack trace ("~" means nesting-related): - Failed at: ${item.id} [in template "article/detail/index.ftl" at line 48, column 106] ---- Java stack trace (for programmers): ---- freemarker.core.InvalidReferenceException: [... Exception message was already printed; see it above ...] at freemarker.core.InvalidReferenceException.getInstance(InvalidReferenceException.java:134) at freemarker.core.EvalUtil.coerceModelToTextualCommon(EvalUtil.java:481) at freemarker.core.EvalUtil.coerceModelToStringOrMarkup(EvalUtil.java:401) at freemarker.core.EvalUtil.coerceModelToStringOrMarkup(EvalUtil.java:370) at freemarker.core.DollarVariable.calculateInterpolatedStringOrMarkup(DollarVariable.java:104) at freemarker.core.DollarVariable.accept(DollarVariable.java:63) at freemarker.core.Environment.visit(Environment.java:371) at freemarker.core.IteratorBlock$IterationContext.executedNestedContentForCollOrSeqListing(IteratorBlock.java:321) at freemarker.core.IteratorBlock$IterationContext.executeNestedContent(IteratorBlock.java:271) at freemarker.core.IteratorBlock$IterationContext.accept(IteratorBlock.java:244) at freemarker.core.Environment.visitIteratorBlock(Environment.java:645) at freemarker.core.IteratorBlock.acceptWithResult(IteratorBlock.java:108) at freemarker.core.IteratorBlock.accept(IteratorBlock.java:94) at freemarker.core.Environment.visit(Environment.java:335) at freemarker.core.Environment.visit(Environment.java:341) at freemarker.core.Environment.visit(Environment.java:341) at freemarker.core.Environment.process(Environment.java:314) at freemarker.template.Template.process(Template.java:383) at org.springframework.web.servlet.view.freemarker.FreeMarkerView.processTemplate(FreeMarkerView.java:332) at org.springframework.web.servlet.view.freemarker.FreeMarkerView.doRender(FreeMarkerView.java:266) at org.springframework.web.servlet.view.freemarker.FreeMarkerView.renderMergedTemplateModel(FreeMarkerView.java:220) at org.springframework.web.servlet.view.AbstractTemplateView.renderMergedOutputModel(AbstractTemplateView.java:181) at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:314) at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1431) at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1167) at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1106) at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014) at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:903) at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:564) at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885) at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:205) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) at com.software.filter.HttpSpiderIdentifyFilter.doFilter(HttpSpiderIdentifyFilter.java:51) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:482) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:115) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:340) at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:391) at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63) at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:896) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1744) at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) at java.base/java.lang.VirtualThread.run(VirtualThread.java:309)