Linux 服务脚本 start.sh、run.sh 和 stop.sh 的示例详解 [复制链接]
发表于 2025-5-17 03:58:01 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×

本文是博主在整理项目时所记,关于 run.sh 文件中的 JVM 参数在高版本下大概不适用,本文是基于JDK 8的版本。如果碰到使用了 ./run.sh 后项目不能正确被拉起,而使用的又不是 JAVA 8,则很大大概是 JVM 参数问题。


  
1、start.sh 脚本

  1. # !/bin/bash
  2. ServiceName="ServiceHost"
  3. BASEPATH="/wen/Web.Test.Service"
  4. #修改打开的文件句柄数量,可以根据需要选择是否设置
  5. ulimit -n 100000
  6. cd $BASEPATH
  7. #设置部署目录用户权限
  8. chown -R dev:users $BASEPATH
  9. find $BASEPATH -type d -exec chmod 0750 {} \;
  10. find $BASEPATH -type f -exec chmod 0640 {} \;
  11. chmod 740 bin/*.sh
  12. # /bin/su -p dev -c ./bin/run.sh (推荐)
  13. /bin/su -p -c ./bin/run.sh dev
复制代码
2、start.sh 剖析

这个 Bash 脚本重要用于启动一个名为 ServiceHost 的服务,并进行了一系列的环境设置和权限设置。


  • 1、脚本声明和变量界说:
    1. #!/bin/bash
    2. ServiceName="ServiceHost"
    3. BASEPATH="/wen/Web.Test.Service"
    复制代码

    • #!/bin/bash:这是脚本的 shebang 行,指定了脚本的解释器为 /bin/bash。
    • ServiceName="ServiceHost":界说了一个变量 ServiceName,用于存储服务名称。
    • BASEPATH="/wen/Web.Test.Service":界说了一个变量 BASEPATH,表现服务的基路径。

  • 2、修改打开的文件句柄数量::
    1. ulimit -n 100000
    复制代码

    • ulimit -n 100000
      :设置当前 shell 进程可以打开的文件描述符的最大数量为 100000 。这对于必要同时处理大量文件或网络连接的服务大概很重要。

  • 3、切换到服务的基路径:
    1. cd $BASEPATH
    复制代码

    • cd $BASEPATH
      :改变当前工作目次到 BASEPATH 变量指定的路径。

  • 4、设置摆设目次的用户权限:
    1. chown -R dev:users $BASEPATH
    2. find $BASEPATH -type d -exec chmod 0750 {} \;
    3. find $BASEPATH -type f -exec chmod 0640 {} \;
    4. chmod 740 bin/*.sh
    复制代码

    • chown -R dev:users $BASEPATH:递归地将 BASEPATH 目次及其下所有文件和子目次的所有者改为 dev 用户,组改为 users 组。
    • find $BASEPATH -type d -exec chmod 0750 {} \;:查找 BASEPATH 下的所有目次,并设置它们的权限为 0750 (所有者有读、写、执行权限,组用户有读、执行权限,其他用户无权限)。
    • find $BASEPATH -type f -exec chmod 0640 {} \;:查找 BASEPATH 下的所有文件,并设置它们的权限为0640(所有者有读、写权限,组用户有读权限,其他用户无权限)。
    • chmod 740 bin/*.sh:将 bin 目次下所有 .sh 脚本文件的权限设置为 740 (所有者有读、写、执行权限,组用户有读权限,其他用户无权限)。

  • 5、以特定用户身份执行启动脚本:
    1. /bin/su -p -c ./bin/run.sh dev
    复制代码

    • /bin/su -p -c ./bin/run.sh dev
      :使用 su 命令以 dev 用户的身份执行 ./bin/run.sh 脚本。
    • -p 选项通常用于提示用户输入密码,但在这个脚本中大概不会生效,因为通常脚本运行不会交互地输入密码。
    • 注意,这里大概有一个误解或错误,因为 -c 选项后应该直接跟要执行的命令字符串,而不是先跟用户。
    • 正确的用法大概依赖于具体的系统设置和 su 的实现,但通常我们盼望看到雷同 su - dev -c "./bin/run.sh" 的形式,或者如果 dev 用户不必要密码切换,可以省略 -p 并直接运行 su - dev -c "./bin/run.sh" 。
    • 表现指定要以目标身份 dev 执行 ./bin/run.sh 命令。

注意:脚本中最后一行大概必要根据现实环境进行调解,以确保以正确的用户身份执行启动脚本。此外,-p 选项在 su 命令中的使用大概必要根据现实环境进行验证,因为它通常用于交互式地提示密码,这在脚本自动化中通常不是盼望的举动。
3、run.sh 脚本

  1. # !/bin/bash
  2. umask 0027
  3. echo "Service is starting..."
  4. export JAVA_HOME=/usr/local/jdk18
  5. export JRE_HOME=$JAVA_HOME/jre
  6. ServiceName="ServiceHost"
  7. BASEPATH="/wen/Web.Test.Service"
  8. cd $BASEPATH
  9. ./bin/stop.shexport LD_LIBRARY_PATH=/wen/commonsdk/expo4:$LD_LIBRARY_PATH
  10. echo "Starting $ServiceName"
  11. nohup java -jar -Xms4096M -Xmx4096M -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./gclogs/dump -verbose:gc -XX:+PrintGCDetails -XX:+PrintHeapAtGC -XX:+PrintGCDateStamps -Xloggc:./gclogs/gc.log ServiceBusHost.jar >/dev/null 2>&1 &echo "LD_LIBRARY_PATH is $LD_LIBRARY_PATH"
  12. echo "$ServiceName is started. "
复制代码
4、run.sh 剖析

这个 Bash 脚本使用的是Shell脚本语言,重要用于启动一个名为 ServiceHost 的 Java 服务,并且包含了一些环境变量的设置和日志日志处理。通常用于Unix和类Unix系统(如Linux和macOS)中自动化任务。


  • 1、脚本声明:
    1. # !/bin/bash
    2. umask 0027
    3. echo "Service is starting..."
    复制代码

    • #!/bin/bash:这是脚本的 shebang 行,指定了脚本的解释器为 /bin/bash。
    • umask 0027: umask(用户文件创建模式掩码)是一个设置文件权限的命令。决定了新创建文件和目次的默认权限。 0027是一个八进制数,表现掩码值。
    • 在 Unix 和 类Unix 系统中,文件和目次的权限由三组数字表现(例如 rwxr-xr-- 可以表现为 755 ),对应所有者 owner、组 group 和其他用户 others 的读 r 、写 w 和执行 x 权限。
    • umask 值从默认权限中减去,以确定新创建文件和目次的现实权限。对于文件,默认权限是666(rw-rw-rw-),对于目次是777(rwxrwxrwx)。
    • 因此,umask 0027 意味着从默认权限中减去 ----w--w- (即其他用户的写权限和组的写权限)。对于文件,这将导致新文件的权限为644(rw-r–r–),对于目次,则为750(rwxr-x—)。
    • echo "Service is starting...":echo 是一个用于在终端输出文本的命令。"Service is starting..." 是 echo 命令要输出的字符串。

  • 2、变量界说:
    1. export JAVA_HOME=/usr/local/jdk18
    2. export JRE_HOME=$JAVA_HOME/jre
    3. ServiceName="ServiceHost"
    4. BASEPATH="/wen/Web.Test.Service"
    复制代码

    • export JAVA_HOME=/usr/local/jdk18:设置 JAVA_HOME 环境变量,指向Java开辟工具包(JDK)的安装目次。这里使用的是JDK 18 。
    • export JRE_HOME=$JAVA_HOME/jre:设置 JRE_HOME 环境变量,指向Java运行时环境(JRE)的目次。这个目次是 JAVA_HOME 下的 jre 子目次。
    • ServiceName="ServiceBusHost":界说服务名称变量 ServiceName ,用于后续脚本中引用服务名称。
    • BASEPATH="/wen/Web.Test.Service":界说基础路径变量 BASEPATH ,这是服务所在目次的路径。

  • 3、切换到服务目次并停止服务:
    1. cd $BASEPATH
    2. ./bin/stop.sh
    复制代码

    • cd $BASEPATH
      :切换到 BASEPATH 指定的目次,即服务的根目次。
    • ./bin/stop.sh:执行当前目次下的 bin 子目次中的 stop.sh 脚本,用于停止已经运行的服务。

  • 4、设置 LD_LIBRARY_PATH 和 日志日志
    1. export LD_LIBRARY_PATH=/wen/commonsdk/expo4:$LD_LIBRARY_PATH
    2. echo "Starting $ServiceName"
    复制代码

    • export LD_LIBRARY_PATH=/wind/commonsdk/expo4LD_LIBRARY_PATH:设置 LD_LIBRARY_PATH 环境变量,用于指定动态链接器搜索共享库时应该查找的目次。这里将 /wind/commonsdk/expo4 添加到 LD_LIBRARY_PATH 的最前面,保留原有值。
    • echo "Starting $ServiceName":打印开始启动服务的消息。

  • 5、后台启动一个Java应用步伐:
    1. nohup java -jar -Xms4096M -Xmx4096M -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./gclogs/dump -verbose:gc -XX:+PrintGCDetails -XX:+PrintHeapAtGC -XX:+PrintGCDateStamps -Xloggc:./gclogs/gc.log ServiceHost.jar >/dev/null 2>&1 &
    复制代码

    • 用于在后台启动一个 Java 步伐(ServiceHost.jar),并设置了一系列的Java虚拟机(JVM)参数以及日志日志记载选项。
    • nohup:用于在用户注销 logout 后继续运行相应的命令,用于在你退出 shell 或终端会话后继续运行命令。
    • java -jar:这是 Java命令,用于运行一个打包成 JAR(Java ARchive)文件的应用步伐。
    • -Xms4096M -Xmx4096M:设置 JVM 的初始堆巨细(-Xms)和最大堆巨细(-Xmx)为 4096MB(即4GB)。
    • -XX:+HeapDumpOnOutOfMemoryError**:当 JVM 抛出 OutOfMemoryError 时,自动天生堆转储快照(heap dump)。
    • -XX:HeapDumpPath=./gclogs/dump:指定堆转储快照保存的路径。
    • -verbose:gc -XX:+PrintGCDetails -XX:+PrintHeapAtGC -XX:+PrintGCDateStamps:这些参数用于开启 GC(垃圾回收)日志的具体记载,包罗每次 GC 前后堆的具体环境、GC 发生的日期时间戳等。
    • -Xloggc:./gclogs/gc.log:指定 GC 日志的输出文件路径。
    • ServiceBusHost.jar:这是要运行的 JAR 文件的名字。
    • >/dev/null 2>&1:这部分将标准输出(stdout)和标准错误输出(stderr)都重定向到 /dev/null ,即忽略所有输出。

      • >:是重定向操作符,/dev/null 是一个特殊的设备文件,向其写入的内容都会被抛弃。
      • 2>&1:表现将标准错误输出重定向到标准输出的当前位置(在这里是/dev/null)。

    • &:在命令末端,这个符号表现将该命令置于后台执行。

  • 5、输出信息:
    1. echo "LD_LIBRARY_PATH is $LD_LIBRARY_PATH"
    2. echo "$ServiceName is started. "
    复制代码

    • echo "LD_LIBRARY_PATH is $LD_LIBRARY_PATH":打印环境变量 LD_LIBRARY_PATH 的值,这个变量通常用于指定动态链接器搜索共享库时应该搜索的目次。
    • echo "$ServiceName is started. ":打印一条消息表现服务已经启动。这里 $ServiceName 是一个变量,提供服务名字。

5、stop.sh 脚本

  1. #!/bin/bash
  2. AppName=ServiceHost
  3. ProcessName=ServiceHost.jar
  4. cd /wen/WebService
  5. is_exist(){
  6.         pid=`ps -efww | grep $ProcessName | grep -v grep | awk '{print $2}'`
  7.         if [ -z "${pid}" ]; then
  8.                 return 1
  9.         else
  10.             return 0
  11.         fi
  12. }
  13. while true
  14. do
  15.         is_exist
  16.         if [ $? -eq "0" ]; then
  17.                 echo "$AppName is running, it is being stopped, please wait moment."
  18.             kill ${pid}
  19.             sleep 5
  20.         else
  21.             echo "$AppName is stopped."
  22.             break
  23.         fi
  24. done
复制代码
6、stop.sh 剖析

这个脚本的重要功能是检查一个名为 ServiceBusHost.jar 的进程是否存在,如果存在,则停止它。


  • 1、界说变量并切换目次:
    1. #!/bin/bash
    2. AppName=ServiceHost
    3. ProcessName=ServiceHost.jar
    4. cd /wen/WebService
    复制代码

    • #!/bin/bash:这是脚本的 shebang 行,指定了脚本的解释器为 /bin/bash。
    • AppName=ServiceHost:界说应用名称为 ServiceHost。
    • ProcessName=ServiceHost.jar:界说进程名称为 ServiceHost.jar 。这个名称用于在系统中搜索运行的进程。
    • cd /wind/Wind.iSeller.JService:将当前工作目次切换到 /wen/WebService 。这通常是 ServiceHost.jar 文件所在的目次,或者是启动该进程的脚本所在的目次。

  • 2、界说函数 is_exist :
    1. is_exist(){
    2.         pid=`ps -efww | grep $ProcessName | grep -v grep | awk '{print $2}'`
    3.         if [ -z "${pid}" ]; then
    4.                    return 1
    5.         else
    6.                 return 0
    7.         fi
    8. }
    复制代码

    • 这个函数用于检查 ServiceHost.jar 进程是否存在。
    • 使用 ps -efww 命令列出系统中所有进程的具体信息。
    • grep $ProcessName 从所有进程中筛选出包含 ServiceHost.jar 的行。
    • grep -v grep 排除掉包含 grep 命令本身的行,因为 grep 命令本身也会出现在 ps 命令的输出中。
    • awk '{print $2}' 从筛选出的行中提取进程 ID(PID),这是每行的第二个字段。
    • 如果找到的 PID 为空(即 -z "${pid}"),表现进程不存在,函数返回 1;否则,表现进程存在,函数返回 0。

  • 3、循环检查进程并尝试停止:
    1. while true
    2. do
    3.         is_exist
    4.         if [ $? -eq "0" ]; then
    5.                 echo "$AppName is running, it is being stopped, please wait moment."
    6.             kill ${pid}
    7.             sleep 5
    8.         else
    9.             echo "$AppName is stopped."
    10.             break
    11.         fi
    12. done
    复制代码

    • 使用 while true 创建一个无穷循环。
    • 在循环中调用 is_exist 函数。
    • 如果函数返回 0(即进程存在),则执行以下操作:

      • 打印一条消息,说明 AppName 正在运行,并且即将被停止。
        - 使用 kill ${pid} 命令停止进程。${pid} 是之前通过 is_exist 函数找到的进程ID。
        - sleep 5 命令让脚本停息5秒,这通常是为了等待进程完全停止。

    • 如果函数返回 1(即进程不存在),则执行以下操作:

      • 打印一条消息,说明 AppName 已经停止。
      • 使用 break 命令退出循环。


注意事项:


  • 脚本中使用的 kill 命令默认发送 SIGTERM 信号给进程,这是请求进程正常停止的标准方式。如果进程不相应 SIGTERM,大概必要使用 SIGKILL(即 kill -9 ${pid})来强制停止进程。
  • 在生产环境中,直接杀死进程大概不是最佳实践,因为它不答应进程进行任何须要的清理工作。更优雅的方式大概是通过发送特定的停止命令或信号给进程,让进程可以或许本身优雅地关闭。
  • 脚本假设 ServiceHost.jar 进程的名称是唯一的,并且不会与其他进程名混淆。如果系统中有多个雷同名称的进程,这个脚本大概会错误地停止错误的进程。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表