<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>nolancode (nolan)</title>
    <link>https://ruby-china.org/nolancode</link>
    <description/>
    <language>en-us</language>
    <item>
      <title> 后端开发必备：生产环境异常自动电话通知方案</title>
      <description>&lt;h2 id="后端开发必备：生产环境异常自动电话通知方案"&gt;后端开发必备：生产环境异常自动电话通知方案&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;生产环境出 bug 了但没及时发现？支付接口异常导致资损？这个语音通知方案专为开发者打造，重要异常直接打电话，让你第一时间响应处理！&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;作为开发者，我们最怕的就是生产环境出现异常却没有及时发现。飞书群、钉钉群报警很容易错过，尤其是深夜或周末。今天分享一个专门针对开发者的语音电话通知解决方案，让重要异常第一时间电话通知到你。&lt;/p&gt;
&lt;h3 id="🎯 典型使用场景"&gt;🎯 典型使用场景&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;需要立即电话通知的开发场景：&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🚨 API 接口异常或超时&lt;/li&gt;
&lt;li&gt;💰 支付流程异常（防止资损）&lt;/li&gt;
&lt;li&gt;📊 数据处理任务失败&lt;/li&gt;
&lt;li&gt;🔐 用户登录异常激增&lt;/li&gt;
&lt;li&gt;⚡ 核心业务逻辑报错&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="🚀 3步快速集成"&gt;🚀 3 步快速集成&lt;/h3&gt;&lt;table class="table table-bordered table-striped"&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;th&gt;步骤&lt;/th&gt;
&lt;th&gt;操作说明&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1️⃣ 扫码注册&lt;/td&gt;
&lt;td&gt;访问 &lt;a href="https://push.spug.cc" rel="nofollow" target="_blank" title=""&gt;push.spug.cc&lt;/a&gt;，微信扫码登录&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2️⃣ 创建模板&lt;/td&gt;
&lt;td&gt;新建消息模板 → 语音通道 → 语音模板 → 动态推送对象&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3️⃣ 集成代码&lt;/td&gt;
&lt;td&gt;复制 API 地址，添加到异常处理代码中&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;img src="https://cdn.spug.cc/push/guide/push-template-voice.png" title="" alt="语音通知模板配置"&gt;&lt;/p&gt;
&lt;h3 id="💻 代码集成示例"&gt;💻 代码集成示例&lt;/h3&gt;&lt;h4 id="🐍 Python（异常处理）"&gt;🐍 Python（异常处理）&lt;/h4&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;send_voice_alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;phone&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;发送语音告警&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://push.spug.cc/send/A27L****bgEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;key1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;targets&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;phone&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;语音告警发送失败: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# 在异常处理中使用
&lt;/span&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# 你的业务代码
&lt;/span&gt;    &lt;span class="nf"&gt;process_payment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;PaymentException&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# 支付异常立即电话通知
&lt;/span&gt;    &lt;span class="nf"&gt;send_voice_alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;支付异常: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;186xxxx9898&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="☕ Java（Spring Boot异常处理）"&gt;☕ Java（Spring Boot 异常处理）&lt;/h4&gt;&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Component&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;VoiceAlertService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;RestTemplate&lt;/span&gt; &lt;span class="n"&gt;restTemplate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RestTemplate&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="no"&gt;VOICE_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"https://push.spug.cc/send/A27L****bgEY"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;sendVoiceAlert&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;phone&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HashMap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
            &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"key1"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"targets"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;phone&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

            &lt;span class="nc"&gt;HttpHeaders&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HttpHeaders&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
            &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setContentType&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;MediaType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;APPLICATION_JSON&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="nc"&gt;HttpEntity&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;entity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HttpEntity&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

            &lt;span class="n"&gt;restTemplate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;postForEntity&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;VOICE_URL&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"语音告警发送失败: {}"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getMessage&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// 全局异常处理器&lt;/span&gt;
&lt;span class="nd"&gt;@ControllerAdvice&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GlobalExceptionHandler&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Autowired&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;VoiceAlertService&lt;/span&gt; &lt;span class="n"&gt;voiceAlertService&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@ExceptionHandler&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;CriticalException&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;ResponseEntity&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;handleCriticalException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;CriticalException&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// 关键异常立即电话通知&lt;/span&gt;
        &lt;span class="n"&gt;voiceAlertService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sendVoiceAlert&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"API异常: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getMessage&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="s"&gt;"186xxxx9898"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ResponseEntity&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Internal Server Error"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="🔧 实际开发场景"&gt;🔧 实际开发场景&lt;/h3&gt;&lt;h4 id="场景1: 支付接口监控"&gt;场景 1: 支付接口监控&lt;/h4&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_order_payment&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;payment_service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_order&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;success&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;send_voice_alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;支付订单创建失败&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;186xxxx9898&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;send_voice_alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;支付系统异常: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;186xxxx9898&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="场景2: 定时任务监控"&gt;场景 2: 定时任务监控&lt;/h4&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;daily_data_sync&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;sync_user_data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;send_voice_alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;每日数据同步失败&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;186xxxx9898&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="场景3: API响应时间监控"&gt;场景 3: API 响应时间监控&lt;/h4&gt;&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Component&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ApiPerformanceInterceptor&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;HandlerInterceptor&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Autowired&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;VoiceAlertService&lt;/span&gt; &lt;span class="n"&gt;voiceAlertService&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="nf"&gt;preHandle&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HttpServletRequest&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;HttpServletResponse&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; 
                           &lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;handler&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setAttribute&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"startTime"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;currentTimeMillis&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;afterCompletion&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HttpServletRequest&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;HttpServletResponse&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                              &lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;handler&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;startTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Long&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getAttribute&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"startTime"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;duration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;currentTimeMillis&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;startTime&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;duration&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;  &lt;span class="c1"&gt;// 超过5秒&lt;/span&gt;
            &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"API响应慢: %s 耗时%dms"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; 
                                         &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getRequestURI&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;duration&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;voiceAlertService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sendVoiceAlert&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"186xxxx9898"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="📋 参数说明"&gt;📋 参数说明&lt;/h3&gt;&lt;table class="table table-bordered table-striped"&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;th&gt;参数&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;th&gt;示例值&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;key1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;异常消息内容&lt;/td&gt;
&lt;td&gt;&lt;code&gt;"支付接口异常"&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;targets&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;接收电话的手机号&lt;/td&gt;
&lt;td&gt;&lt;code&gt;"186xxxx9898"&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;h3 id="❓ 开发者常见问题"&gt;❓ 开发者常见问题&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;🤔 如何避免告警风暴？&lt;/strong&gt;
建议设置异常频率限制，同类异常 5 分钟内只发送一次。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;💰 语音通话收费吗？&lt;/strong&gt;&lt;br&gt;
语音通话按次计费，建议只对关键异常使用，普通日志用短信或微信。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🛡️ 如何保护 API 安全？&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;不要将 API 地址提交到公开代码仓库&lt;/li&gt;
&lt;li&gt;可以设置 IP 白名单限制调用来源&lt;/li&gt;
&lt;li&gt;建议使用环境变量存储 API 地址&lt;/li&gt;
&lt;/ol&gt;

&lt;hr&gt;
&lt;h3 id="🎉 为什么开发者需要语音通知？"&gt;🎉 为什么开发者需要语音通知？&lt;/h3&gt;
&lt;p&gt;✅ &lt;strong&gt;及时响应&lt;/strong&gt;：生产故障分秒必争，电话比微信更直接&lt;br&gt;
✅ &lt;strong&gt;降低损失&lt;/strong&gt;：支付、订单等关键业务异常能立即处理&lt;br&gt;
✅ &lt;strong&gt;简单集成&lt;/strong&gt;：几行代码搞定，无需复杂配置&lt;br&gt;
✅ &lt;strong&gt;多语言支持&lt;/strong&gt;：Python、Node.js、Java 等任何语言都能用&lt;br&gt;
✅ &lt;strong&gt;个人友好&lt;/strong&gt;：无需企业资质，个人开发者也能用&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;记住：好的开发者不是不写 bug，而是能第一时间发现并修复 bug！&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;网站链接：&lt;a href="https://push.spug.cc" rel="nofollow" target="_blank" title=""&gt;push.spug.cc&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</description>
      <author>nolancode</author>
      <pubDate>Mon, 28 Jul 2025 08:22:06 +0800</pubDate>
      <link>https://ruby-china.org/topics/44235</link>
      <guid>https://ruby-china.org/topics/44235</guid>
    </item>
    <item>
      <title>踩过坑后，我发现了这几个运维神器</title>
      <description>&lt;p&gt;作为一个工作了 8 年的运维开发，踩过的坑数不胜数。从半夜被 SSL 证书过期叫醒，到个人项目发不了短信验证码，再到网站挂了半天才发现...这些痛苦的经历让我不断寻找更好的解决方案。&lt;/p&gt;

&lt;p&gt;今天分享三个我在实际工作中发现的实用工具，希望能帮大家少踩一些坑。&lt;/p&gt;
&lt;h2 id="1. SSL证书管理：告别半夜被叫醒"&gt;1. SSL 证书管理：告别半夜被叫醒&lt;/h2&gt;&lt;h3 id="痛点回顾"&gt;痛点回顾&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;证书突然过期，用户无法访问网站&lt;/li&gt;
&lt;li&gt;手动续费太麻烦，经常忘记&lt;/li&gt;
&lt;li&gt;企业证书动辄几千块，个人项目用不起&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="解决方案：ssl.spug.cc"&gt;解决方案：&lt;a href="https://ssl.spug.cc" rel="nofollow" target="_blank" title=""&gt;ssl.spug.cc&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;核心优势：&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;价格优势明显&lt;/strong&gt;：单域名 39 元/年，比其他平台便宜 87%&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;自动化部署&lt;/strong&gt;：一键部署到阿里云 CDN、OSS、ALB 等&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;到期提醒&lt;/strong&gt;：支持微信、短信等多渠道提醒&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;免费通配符证书&lt;/strong&gt;：个人项目的福音&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;实际体验：&lt;/strong&gt;
之前管理 10 个证书需要 1 小时手动更新，现在 3 分钟自动完成。最关键的是再也没有因为证书过期半夜被叫醒过。&lt;/p&gt;
&lt;h2 id="2. 短信验证码：个人项目也能用"&gt;2. 短信验证码：个人项目也能用&lt;/h2&gt;&lt;h3 id="痛点回顾"&gt;痛点回顾&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;个人开发者很难找到合适的短信服务&lt;/li&gt;
&lt;li&gt;传统平台注册流程复杂，门槛高&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="解决方案：push.spug.cc"&gt;解决方案：&lt;a href="https://push.spug.cc" rel="nofollow" target="_blank" title=""&gt;push.spug.cc&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;核心优势：&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;使用简单&lt;/strong&gt;：微信扫码注册即可使用&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;配置简单&lt;/strong&gt;：3 步完成配置，新手 10 分钟上手&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;按量付费&lt;/strong&gt;：没有最低消费门槛&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;多语言支持&lt;/strong&gt;：Python、JavaScript、cURL 等&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;代码示例：&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;
&lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://push.spug.cc/send/你的模板ID&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;code&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;123456&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;targets&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;手机号&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;个人项目终于可以有短信验证码功能了，而且成本控制得很好。&lt;/p&gt;
&lt;h2 id="3. 电话通知：半夜服务器告警不再错过！"&gt;3. 电话通知：半夜服务器告警不再错过！&lt;/h2&gt;&lt;h3 id="痛点回顾"&gt;痛点回顾&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;半夜服务器宕机错过告警&lt;/li&gt;
&lt;li&gt;企业群消息太多容易错过，导致故障扩大&lt;/li&gt;
&lt;li&gt;需要电话通知，但找不到合适的方案&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="解决方案：push.spug.cc"&gt;解决方案：&lt;a href="https://push.spug.cc" rel="nofollow" target="_blank" title=""&gt;push.spug.cc&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;核心优势：&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;使用简单&lt;/strong&gt;：微信扫码注册即可使用&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;配置简单&lt;/strong&gt;：3 步完成配置，新手 10 分钟上手&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;按量付费&lt;/strong&gt;：没有最低消费门槛&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;多语言支持&lt;/strong&gt;：Python、JavaScript、cURL 等&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;代码示例：&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl https://push.spug.cc/send/A27L&lt;span class="k"&gt;****&lt;/span&gt;bgEY &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;"key1=Nginx服务异常&amp;amp;targets=186xxxx9898"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="4. 网站监控：免费且好用"&gt;4. 网站监控：免费且好用&lt;/h2&gt;&lt;h3 id="痛点回顾"&gt;痛点回顾&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;网站挂了不知道，用户投诉才发现&lt;/li&gt;
&lt;li&gt;免费监控功能有限，付费版本太贵&lt;/li&gt;
&lt;li&gt;部署监控系统太复杂&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="解决方案：up.spug.cc"&gt;解决方案：&lt;a href="https://up.spug.cc" rel="nofollow" target="_blank" title=""&gt;up.spug.cc&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;核心优势：&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;完全免费&lt;/strong&gt;：网站监控、TCP 监控、Ping 监控&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;多种监控类型&lt;/strong&gt;：支持 HTTP、域名、SSL 证书、端口监控&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;多渠道报警&lt;/strong&gt;：电话、短信、微信、钉钉、飞书等&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;免部署&lt;/strong&gt;：开箱即用，无需搭建&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;功能亮点：&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SSL 证书到期提醒&lt;/li&gt;
&lt;li&gt;域名到期监控&lt;/li&gt;
&lt;li&gt;网站可用性实时监控&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;现在网站有任何异常都能第一时间知道，再也不用担心服务悄悄挂掉了。&lt;/p&gt;
&lt;h2 id="我的使用建议"&gt;我的使用建议&lt;/h2&gt;&lt;h3 id="适用场景"&gt;适用场景&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;个人开发者&lt;/strong&gt;：这几个工具都支持个人使用，门槛低&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;小型团队&lt;/strong&gt;：成本控制好，功能够用&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;中小企业&lt;/strong&gt;：性价比高，可以替代昂贵的企业方案&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="实际成本对比"&gt;实际成本对比&lt;/h3&gt;&lt;table class="table table-bordered table-striped"&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;th&gt;需求&lt;/th&gt;
&lt;th&gt;传统方案成本&lt;/th&gt;
&lt;th&gt;推荐方案成本&lt;/th&gt;
&lt;th&gt;节省&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SSL 证书&lt;/td&gt;
&lt;td&gt;300-500 元/年&lt;/td&gt;
&lt;td&gt;39 元/年&lt;/td&gt;
&lt;td&gt;87%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;短信验证码&lt;/td&gt;
&lt;td&gt;企业认证 + 高门槛&lt;/td&gt;
&lt;td&gt;按量付费&lt;/td&gt;
&lt;td&gt;大幅降低&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;电话通知&lt;/td&gt;
&lt;td&gt;企业认证 + 高门槛&lt;/td&gt;
&lt;td&gt;按量付费&lt;/td&gt;
&lt;td&gt;大幅降低&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;网站监控&lt;/td&gt;
&lt;td&gt;几百到几千/年&lt;/td&gt;
&lt;td&gt;免费&lt;/td&gt;
&lt;td&gt;100%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;h2 id="写在最后"&gt;写在最后&lt;/h2&gt;
&lt;p&gt;这几个工具我用了一年多，确实解决了不少实际问题。特别是对个人开发者和小团队来说，能大幅降低成本和技术门槛。&lt;/p&gt;

&lt;p&gt;当然，工具选择因人而异，适合自己的才是最好的。如果你也有类似的痛点，不妨试试看。&lt;/p&gt;

&lt;hr&gt;

&lt;p&gt;&lt;strong&gt;相关链接：&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SSL 证书平台：&lt;a href="https://ssl.spug.cc" rel="nofollow" target="_blank"&gt;https://ssl.spug.cc&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;短信电话推送平台：&lt;a href="https://push.spug.cc" rel="nofollow" target="_blank"&gt;https://push.spug.cc&lt;/a&gt;&lt;br&gt;
&lt;/li&gt;
&lt;li&gt;监控平台：&lt;a href="https://up.spug.cc" rel="nofollow" target="_blank"&gt;https://up.spug.cc&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;</description>
      <author>nolancode</author>
      <pubDate>Tue, 22 Jul 2025 07:43:15 +0800</pubDate>
      <link>https://ruby-china.org/topics/44226</link>
      <guid>https://ruby-china.org/topics/44226</guid>
    </item>
    <item>
      <title>个人开发者如何发送短信？这个方案太香了！</title>
      <description>&lt;blockquote&gt;
&lt;p&gt;还在为无法发送短信验证码而烦恼？今天分享一个超实用的解决方案，个人开发者也能用！&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;最近国内很多平台暂停了针对个人用户的短信发送，这给个人开发者带来了不少困扰。不过别担心，一个超实用的解决方案——Spug 推送平台，它能很好地满足我们发送短信验证码等需求。&lt;/p&gt;
&lt;h2 id="为什么选择这个方案？"&gt;为什么选择这个方案？&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;无需企业认证&lt;/strong&gt;：个人开发者直接可用&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;新用户福利&lt;/strong&gt;：注册即送测试短信&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;价格实惠&lt;/strong&gt;：0.05 元/条，按量计费&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;接口简单&lt;/strong&gt;：几行代码就能搞定&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;支持丰富&lt;/strong&gt;：短信、电话、微信、企业微信、飞书、钉钉、邮件等&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="三步搞定短信发送"&gt;三步搞定短信发送&lt;/h2&gt;&lt;h3 id="第一步：注册账户"&gt;第一步：注册账户&lt;/h3&gt;
&lt;p&gt;打开&lt;a href="https://push.spug.cc" rel="nofollow" target="_blank" title=""&gt;push.spug.cc&lt;/a&gt;，使用微信扫码直接登录，无需繁琐的认证流程。&lt;/p&gt;
&lt;h3 id="第二步：创建模板"&gt;第二步：创建模板&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;点击"消息模板" → "新建"&lt;/li&gt;
&lt;li&gt;输入模版名称&lt;/li&gt;
&lt;li&gt;选择推送通道&lt;/li&gt;
&lt;li&gt;选择短信验证码模板&lt;/li&gt;
&lt;li&gt;选择推送对象&lt;/li&gt;
&lt;li&gt;保存模板&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="第三步：发送验证码"&gt;第三步：发送验证码&lt;/h3&gt;
&lt;p&gt;复制模版 ID，通过 API 调用即可发送短信验证码。&lt;/p&gt;
&lt;h2 id="代码示例（多种语言）"&gt;代码示例（多种语言）&lt;/h2&gt;&lt;h3 id="Ruby版"&gt;Ruby 版&lt;/h3&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'net/http'&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'uri'&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;send_sms&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;template_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;phone&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;URI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"https://push.spug.cc/send/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;template_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;?code=&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;amp;targets=&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;phone&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Net&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;HTTP&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_a?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Net&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;HTTPSuccess&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;body&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="s2"&gt;"HTTP request failed with status code: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;code&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;begin&lt;/span&gt;
  &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;send_sms&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'abc'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'6677'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'151xxxx0875'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
&lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;StandardError&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Error: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;message&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="Python版（推荐）"&gt;Python 版（推荐）&lt;/h3&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;send_sms&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;template_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;phone&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://push.spug.cc/send/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;template_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;code&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;targets&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;phone&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# 使用示例
&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;send_sms&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;abc&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;6677&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;151xxxx0875&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="Go版"&gt;Go 版&lt;/h3&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"net/http"&lt;/span&gt;
    &lt;span class="s"&gt;"io/ioutil"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;sendSMS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;templateID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;phone&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://push.spug.cc/send/%s?code=%s&amp;amp;targets=%s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="n"&gt;templateID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;phone&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Body&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;ioutil&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReadAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;sendSMS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"abc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"6677"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"151xxxx0875"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="使用技巧"&gt;使用技巧&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;参数说明&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;code&lt;/code&gt;：验证码内容&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;targets&lt;/code&gt;：接收短信的手机号&lt;/li&gt;
&lt;li&gt;使用&lt;code&gt;targets&lt;/code&gt;参数会覆盖模板配置的手机号&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;最佳实践&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;选择合适的短信模板&lt;/li&gt;
&lt;li&gt;验证手机号格式&lt;/li&gt;
&lt;li&gt;管理验证码有效期&lt;/li&gt;
&lt;li&gt;添加错误处理&lt;/li&gt;
&lt;li&gt;确保账户余额充足&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;</description>
      <author>nolancode</author>
      <pubDate>Fri, 25 Apr 2025 06:58:02 +0800</pubDate>
      <link>https://ruby-china.org/topics/44144</link>
      <guid>https://ruby-china.org/topics/44144</guid>
    </item>
    <item>
      <title>轻量级开源自动化运维平台，批量执行、在线终端、发布部署一应俱全</title>
      <description>&lt;p&gt;&lt;a href="https://github.com/openspug/spug" rel="nofollow" target="_blank" title=""&gt;Spug&lt;/a&gt; 是专为中小型企业设计的轻量级、无 Agent 的自动化运维平台。它整合了主机管理、批量执行、应用部署、监控、报警等核心功能，它以开源的方式，为企业提供了一个全面、高效的运维解决方案。&lt;/p&gt;
&lt;h2 id="主要功能亮点："&gt;主要功能亮点：&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;批量执行&lt;/strong&gt;：在线批量执行主机命令，简化操作&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;在线终端&lt;/strong&gt;：通过浏览器直接登录主机终端&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;文件管理&lt;/strong&gt;：支持文件在线上传、下载&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;任务计划&lt;/strong&gt;：灵活的在线任务调度和计划&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;发布部署&lt;/strong&gt;：自定义发布部署流程&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;配置中心&lt;/strong&gt;：支持多种格式的配置管理（KV、文本、JSON 等）&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;监控报警&lt;/strong&gt;：支持站点、端口、进程等多维度监控，集成短信、邮件、钉钉、微信等报警方式&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="技术亮点"&gt;技术亮点&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;优雅美观&lt;/strong&gt;：基于 Ant Design 的 UI 界面，提供良好的用户体验。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;开源免费&lt;/strong&gt;：前后端代码完全开源，自由使用和修改。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;开源地址：&lt;a href="https://github.com/openspug/spug" rel="nofollow" target="_blank" title=""&gt;https://github.com/openspug/spug&lt;/a&gt;&lt;/p&gt;</description>
      <author>nolancode</author>
      <pubDate>Tue, 24 Sep 2024 19:59:45 +0800</pubDate>
      <link>https://ruby-china.org/topics/43892</link>
      <guid>https://ruby-china.org/topics/43892</guid>
    </item>
  </channel>
</rss>
