NodeBlockedDetection.php 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. <?php
  2. namespace App\Console\Commands;
  3. use App\Components\Helpers;
  4. use App\Components\NetworkDetection;
  5. use App\Components\ServerChan;
  6. use App\Http\Models\SsNode;
  7. use App\Mail\nodeCrashWarning;
  8. use Cache;
  9. use Illuminate\Console\Command;
  10. use Log;
  11. use Mail;
  12. class NodeBlockedDetection extends Command
  13. {
  14. protected static $systemConfig;
  15. protected $signature = 'nodeBlockedDetection';
  16. protected $description = '节点阻断检测';
  17. public function __construct()
  18. {
  19. parent::__construct();
  20. self::$systemConfig = Helpers::systemConfig();
  21. }
  22. public function handle()
  23. {
  24. $jobStartTime = microtime(TRUE);
  25. if(self::$systemConfig['nodes_detection']){
  26. $this->checkNodes();
  27. }
  28. $jobEndTime = microtime(TRUE);
  29. $jobUsedTime = round(($jobEndTime-$jobStartTime), 4);
  30. Log::info("---【{$this->description}】完成---,耗时 {$jobUsedTime} 秒");
  31. }
  32. // 监测节点状态
  33. private function checkNodes()
  34. {
  35. $nodeList = SsNode::query()->where('is_transit', 0)->where('status', 1)->where('detectionType', '>', 0)->get();
  36. $sendText = FALSE;
  37. $message = "| 线路 | 协议 | 状态 |\r\n| ------ | ------ | ------ |\r\n";
  38. $additionalMessage = '';
  39. foreach($nodeList as $node){
  40. $info = FALSE;
  41. if($node->detectionType == 0){
  42. continue;
  43. }
  44. // 使用DDNS的node先通过gethostbyname获取ipv4地址
  45. if($node->is_ddns){
  46. $ip = gethostbyname($node->server);
  47. if(strcmp($ip, $node->server) != 0){
  48. $node->ip = $ip;
  49. }else{
  50. Log::warning("【节点阻断检测】检测".$node->server."时,IP获取失败".$ip." | ".$node->server);
  51. $this->notifyMaster("{$node->name}动态IP获取失败", "节点**{$node->name}**:** IP获取失败 **");
  52. }
  53. }
  54. if($node->detectionType != 1){
  55. $icmpCheck = NetworkDetection::networkCheck($node->ip, TRUE);
  56. if($icmpCheck != FALSE && $icmpCheck != "通讯正常"){
  57. $message .= "| ".$node->name." | ICMP | ".$icmpCheck." |\r\n";
  58. $sendText = TRUE;
  59. $info = TRUE;
  60. }
  61. }
  62. if($node->detectionType != 2){
  63. $tcpCheck = NetworkDetection::networkCheck($node->ip, FALSE, $node->single? $node->port : NULL);
  64. if($tcpCheck != FALSE && $tcpCheck != "通讯正常"){
  65. $message .= "| ".$node->name." | TCP | ".$tcpCheck." |\r\n";
  66. $sendText = TRUE;
  67. $info = TRUE;
  68. }
  69. }
  70. // 节点检测次数
  71. if($info){
  72. if(self::$systemConfig['numberOfWarningTimes']){
  73. // 已通知次数
  74. $cacheKey = 'numberOfWarningTimes'.$node->id;
  75. if(Cache::has($cacheKey)){
  76. $times = Cache::get($cacheKey);
  77. }else{
  78. // 键将保留12小时,多10分钟防意外
  79. Cache::put($cacheKey, 1, 83800);
  80. $times = 1;
  81. }
  82. if($times < self::$systemConfig['numberOfWarningTimes']){
  83. Cache::increment($cacheKey);
  84. }else{
  85. Cache::forget($cacheKey);
  86. SsNode::query()->where('id', $node->id)->update(['status' => 0]);
  87. $additionalMessage .= "\r\n**节点【{$node->name}】自动进入维护状态**\r\n";
  88. }
  89. }
  90. }
  91. }
  92. //只有在出现阻断线路时,才会发出警报
  93. if($sendText){
  94. $this->notifyMaster("节点阻断警告", "**阻断日志**: \r\n\r\n".$message.$additionalMessage);
  95. Log::info("阻断日志: \r\n".$message.$additionalMessage);
  96. }
  97. }
  98. /**
  99. * 通知管理员
  100. *
  101. * @param string $title 消息标题
  102. * @param string $content 消息内容
  103. *
  104. */
  105. private function notifyMaster($title, $content)
  106. {
  107. if(self::$systemConfig['webmaster_email']){
  108. $logId = Helpers::addEmailLog(self::$systemConfig['webmaster_email'], $title, $content);
  109. Mail::to(self::$systemConfig['webmaster_email'])->send(new nodeCrashWarning($logId));
  110. }
  111. ServerChan::send($title, $content);
  112. }
  113. }