kscript 1.0.5 → 1.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +39 -47
- data/lib/kscript/base.rb +1 -1
- data/lib/kscript/cli.rb +2 -2
- data/lib/kscript/logger.rb +9 -4
- data/lib/kscript/plugins/{kk_apnic_utils.rb → kk_apnic_ip_utils.rb} +2 -2
- data/lib/kscript/plugins/kk_aws_s3_utils.rb +5 -5
- data/lib/kscript/plugins/{kk_es_fingerprint_utils.rb → kk_elastic_cert_finger_utils.rb} +3 -3
- data/lib/kscript/plugins/{kk_ffmpeg_utils.rb → kk_ffmpeg_install_utils.rb} +3 -3
- data/lib/kscript/plugins/{kk_rename_utils.rb → kk_file_rename_utils.rb} +3 -3
- data/lib/kscript/plugins/{kk_ip_utils.rb → kk_ip_lookup_utils.rb} +31 -16
- data/lib/kscript/plugins/{kk_jenkins_utils.rb → kk_jenkins_manage_utils.rb} +3 -3
- data/lib/kscript/plugins/{kk_kibana_utils.rb → kk_kibana_manage_utils.rb} +18 -18
- data/lib/kscript/plugins/{kk_lvm_utils.rb → kk_lvm_manage_utils.rb} +3 -3
- data/lib/kscript/plugins/{kk_optimize_utils.rb → kk_mac_optimize_utils.rb} +3 -3
- data/lib/kscript/plugins/{kk_syscheck_utils.rb → kk_mac_status_utils.rb} +28 -16
- data/lib/kscript/plugins/{kk_portscan_utils.rb → kk_port_scan_utils.rb} +3 -3
- data/lib/kscript/plugins/{kk_projscan_utils.rb → kk_project_scan_utils.rb} +4 -4
- data/lib/kscript/plugins/kk_shell_helper_utils.rb +97 -0
- data/lib/kscript/plugins/{kk_usd_utils.rb → kk_usd_rate_utils.rb} +2 -2
- data/lib/kscript/plugins/{kk_cleaner_utils.rb → kk_vcs_cleaner_utils.rb} +3 -3
- data/lib/kscript/plugins/kk_wg_acl_utils.rb +1 -1
- data/lib/kscript/plugins/kk_wg_pass_utils.rb +1 -1
- data/lib/kscript/plugins.rb +1 -1
- data/lib/kscript/version.rb +1 -1
- metadata +21 -28
- data/lib/kscript/plugins/kk_sh_utils.rb +0 -111
- data/lib/kscript/plugins/kk_top_utils.rb +0 -71
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4c903c89ab57a0f91270b2b320b60981ba56ba5d6e4bb4096eb6bd26ab7b5a61
|
4
|
+
data.tar.gz: 17a2a9d64078442493704bb60065bcc14a4b5728dcf1b7caf2440f0ce80c0008
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f27cd8c019f492bd37359c01e0ca710ecc3ec99818b795efc3fd7a688ff4b06b47892421e01c7ceda79066c44184f60d86cfa07ed0c79df9db97dc367cb358cb
|
7
|
+
data.tar.gz: e83ee610a5684dea38c12a68933e23224dee8b2654e9c689ed81ae57e4ee6c7f52620fec51347d6b1f9288075b10e1a42fa041ae8a8c4c4c61614e04ce8dfc51
|
data/README.md
CHANGED
@@ -12,20 +12,20 @@ _ ,< _(__ )/ /__ _ / _ / __ /_/ / /_
|
|
12
12
|
[](https://rubygems.org/gems/kscript)
|
13
13
|
[](https://github.com/kevin197011/kscript/actions/workflows/gem-push.yml)
|
14
14
|
|
15
|
-
> Ruby CLI
|
15
|
+
> Ruby CLI 工具集,专为系统运维、开发自动化、网络与项目管理场景设计。支持插件化、美化输出、自动补全、结构化日志、CI/CD 自动发布等现代特性。
|
16
16
|
|
17
17
|
---
|
18
18
|
|
19
19
|
## ✨ 特性亮点
|
20
|
-
-
|
21
|
-
-
|
22
|
-
-
|
23
|
-
-
|
24
|
-
-
|
25
|
-
-
|
26
|
-
-
|
27
|
-
-
|
28
|
-
-
|
20
|
+
- 统一 CLI 框架,所有命令一键调用,美化输出
|
21
|
+
- 插件化架构,业务命令即插件,易扩展、易维护
|
22
|
+
- 美化输出:ASCII banner、彩色分组、分隔线
|
23
|
+
- 人性化/结构化日志双模式:`--log`/`--log-level` 切换,支持 JSON/终端友好输出
|
24
|
+
- 自动补全:zsh/bash 补全脚本自动部署
|
25
|
+
- 参数健壮:所有插件兼容多余参数,支持全局参数过滤
|
26
|
+
- CI/CD 自动发布:GitHub Actions 自动构建并推送 RubyGem
|
27
|
+
- 多平台支持:macOS、Linux,部分工具支持 Windows
|
28
|
+
- 自动生成配置:首次安装自动生成 `~/.kscript/.env` 配置示例
|
29
29
|
|
30
30
|
---
|
31
31
|
|
@@ -67,17 +67,17 @@ kscript version
|
|
67
67
|
```bash
|
68
68
|
kscript <command> [args...]
|
69
69
|
# 例如
|
70
|
-
kscript
|
71
|
-
kscript
|
72
|
-
kscript
|
73
|
-
kscript
|
70
|
+
kscript apnic_ip CN
|
71
|
+
kscript port_scan 192.168.1.1
|
72
|
+
kscript shell_helper 'ls -l'
|
73
|
+
kscript project_scan ~/projects
|
74
74
|
kscript aws_s3 --file local.txt --bucket my-bucket --key test.txt --region ap-northeast-1 --access_key xxx --secret_key yyy
|
75
75
|
```
|
76
76
|
|
77
77
|
### 结构化日志模式
|
78
78
|
```bash
|
79
|
-
kscript
|
80
|
-
kscript
|
79
|
+
kscript apnic_ip CN --log
|
80
|
+
kscript port_scan 192.168.1.1 --log-level=debug
|
81
81
|
```
|
82
82
|
|
83
83
|
---
|
@@ -86,40 +86,32 @@ kscript portscan 192.168.1.1 --log-level=debug
|
|
86
86
|
|
87
87
|
> 运行 `kscript list` 可分组美化展示所有插件命令
|
88
88
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
- **ci**
|
110
|
-
- `jenkins`:Jenkins Job 导入导出
|
111
|
-
- **cloud**
|
112
|
-
- `aws_s3`:AWS S3 文件上传测试
|
113
|
-
- **其它**
|
114
|
-
- `usd`:美元汇率工具
|
115
|
-
- `lvm`:LVM 卷管理
|
116
|
-
- `windows_font_enhancer`:Windows 字体增强
|
89
|
+
| 分组 | 命令 | 用法示例 | 参数说明 | 描述 |
|
90
|
+
|-----------|------------------------|------------------------------------------------------------------|--------------------------------------------------------|--------------------------------------------------------------|
|
91
|
+
| network | `apnic_ip` | `kscript apnic_ip CN` | `[country_code]` | Get APNIC IPv4 ranges for a country. |
|
92
|
+
| network | `port_scan` | `kscript port_scan 192.168.1.1` | `<target_host> [ports] [thread_count]` | Scan open ports on a target host. |
|
93
|
+
| network | `ip_lookup` | `kscript ip_lookup 8.8.8.8` | `<ip_address>` | Query IP geolocation and ISP info. |
|
94
|
+
| network | `wg_acl` | `kscript wg_acl add --ip=10.0.0.2` | `[subcommand] [options]` | Manage WireGuard firewall ACL rules. |
|
95
|
+
| network | `wg_pass` | `kscript wg_pass 32` | `[length]` | Generate a random password for WireGuard. |
|
96
|
+
| project | `project_scan` | `kscript project_scan ~/projects/src` | `[src_path]` | Scan and list all git projects in a directory. |
|
97
|
+
| project | `vcs_cleaner` | `kscript vcs_cleaner ~/projects/src` | `[src_path]` | Clean old source code versions, keep N latest. |
|
98
|
+
| project | `file_rename` | `kscript file_rename foo bar ./src` | `<pattern> <replacement> [path]` | Batch rename files by pattern. |
|
99
|
+
| system | `shell_helper` | `kscript shell_helper 'ls'` | `[subcommand] [args...]` | Query shell command usage and cheatsheets. |
|
100
|
+
| system | `lvm_manage` | `kscript lvm_manage /dev/sda2 /mnt/data` | `<device> <mount_point>` | Mount and manage Linux LVM volumes. |
|
101
|
+
| macos | `mac_status` | `kscript mac_status` | | Show macOS system resource monitor report. |
|
102
|
+
| macos | `mac_optimize` | `kscript mac_optimize` | | Optimize macOS system performance. |
|
103
|
+
| media | `ffmpeg_install` | `kscript ffmpeg_install 6.0` | `[version]` | Install and verify FFmpeg on Linux. |
|
104
|
+
| elastic | `elastic_cert_finger` | `kscript elastic_cert_finger ./ca.crt` | `<cert_file>` | Generate Elasticsearch certificate SHA256 fingerprint. |
|
105
|
+
| elastic | `kibana_manage` | `kscript kibana_manage export --host=localhost --index=log-*` | `[subcommand] [options]` | Kibana automation: space, index, user, role management. |
|
106
|
+
| ci | `jenkins_manage` | `kscript jenkins_manage list --host=jenkins.local` | `[subcommand] [options]` | Jenkins job export/import automation. |
|
107
|
+
| cloud | `aws_s3` | `kscript aws_s3 --file local.txt --bucket my-bucket ...` | `--file --bucket --key --region --access_key --secret_key` | Upload a file to AWS S3 for testing. |
|
108
|
+
| finance | `usd_rate` | `kscript usd_rate CNY` | `[currency_code]` | Get latest USD exchange rates. |
|
117
109
|
|
118
110
|
---
|
119
111
|
|
120
112
|
## ⚡ Shell 自动补全 & 配置示例
|
121
113
|
|
122
|
-
-
|
114
|
+
- 首次安装/升级自动为 zsh/bash 部署补全脚本,并生成 `~/.kscript/.env` 配置示例
|
123
115
|
- 补全脚本路径:
|
124
116
|
- zsh: `~/.zsh/completions/_kscript`
|
125
117
|
- bash: `~/.bash_completion.d/kscript`
|
@@ -153,7 +145,7 @@ LOG=1
|
|
153
145
|
|
154
146
|
## 🧑💻 插件开发规范
|
155
147
|
- 插件文件统一放在 `lib/kscript/plugins/kk_xxx_utils.rb`
|
156
|
-
- 类名如 `
|
148
|
+
- 类名如 `KkApnicIpUtils`,自动注册为 `apnic_ip` 命令
|
157
149
|
- 支持 `self.description`、`self.usage`、`self.arguments`、`self.group`、`self.author`
|
158
150
|
- 输出统一用 `logger.kinfo`/`logger.kerror`,支持结构化日志
|
159
151
|
- 兼容多余参数,避免 ArgumentError
|
@@ -172,7 +164,7 @@ LOG=1
|
|
172
164
|
## 📦 依赖与兼容性
|
173
165
|
|
174
166
|
- Ruby >= 3.0
|
175
|
-
- 依赖:bcrypt, http, nokogiri, thor, aws-sdk-s3 等
|
167
|
+
- 依赖:bcrypt, http, nokogiri, thor, aws-sdk-s3, httpx 等
|
176
168
|
- 支持 macOS、Linux,部分工具支持 Windows
|
177
169
|
|
178
170
|
---
|
data/lib/kscript/base.rb
CHANGED
@@ -37,7 +37,7 @@ module Kscript
|
|
37
37
|
|
38
38
|
# 判断是否为人性化输出模式(无 --log/--log-level 参数且 ENV['LOG'] 未设置)
|
39
39
|
def human_output?
|
40
|
-
!(ARGV.include?('--log') || ARGV.include?('--log-level') || ENV
|
40
|
+
!(ARGV.include?('--log') || ARGV.include?('--log-level') || ENV.fetch('LOG', nil))
|
41
41
|
end
|
42
42
|
end
|
43
43
|
end
|
data/lib/kscript/cli.rb
CHANGED
@@ -70,7 +70,7 @@ module Kscript
|
|
70
70
|
orig_command = info[:name].to_s.sub(/^kk_/, '')
|
71
71
|
# shell -> sh
|
72
72
|
command = orig_command == 'shell' ? 'sh' : orig_command
|
73
|
-
command =
|
73
|
+
command = "#{command}_cmd" if reserved.include?(command)
|
74
74
|
klass = info[:class]
|
75
75
|
desc command,
|
76
76
|
(info[:description] || 'No description') + (reserved.include?(orig_command) ? " (original: #{orig_command})" : '')
|
@@ -113,7 +113,7 @@ module Kscript
|
|
113
113
|
else
|
114
114
|
puts bold('Loaded environment variables:')
|
115
115
|
keys.sort.each do |k|
|
116
|
-
v = ENV
|
116
|
+
v = ENV.fetch(k, nil)
|
117
117
|
puts green(k.ljust(28)) + gray('=') + cyan(v)
|
118
118
|
end
|
119
119
|
end
|
data/lib/kscript/logger.rb
CHANGED
@@ -5,23 +5,27 @@ module Kscript
|
|
5
5
|
class Logger
|
6
6
|
LEVELS = %i[debug info warn error fatal unknown].freeze
|
7
7
|
|
8
|
-
#
|
8
|
+
# Colorful output
|
9
9
|
COLORS = {
|
10
10
|
info: "\e[32m", # green
|
11
11
|
warn: "\e[33m", # yellow
|
12
12
|
error: "\e[31m", # red
|
13
13
|
debug: "\e[90m", # gray
|
14
|
+
fatal: "\e[35m", # magenta
|
15
|
+
unknown: "\e[36m", # cyan
|
14
16
|
reset: "\e[0m"
|
15
17
|
}.freeze
|
16
18
|
|
17
19
|
def initialize(service: 'kscript', level: :info, out: $stdout, human_output: nil)
|
20
|
+
require 'json'
|
21
|
+
require 'time'
|
18
22
|
@service = service
|
19
23
|
@logger = ::Logger.new(out)
|
20
24
|
@logger.level = ::Logger.const_get(level.to_s.upcase)
|
21
25
|
@human_output = human_output
|
22
26
|
end
|
23
27
|
|
24
|
-
#
|
28
|
+
# 设置人类可读输出模式
|
25
29
|
def set_human_output(val)
|
26
30
|
@human_output = val
|
27
31
|
end
|
@@ -44,6 +48,7 @@ module Kscript
|
|
44
48
|
end
|
45
49
|
end
|
46
50
|
|
51
|
+
# 结构化日志输出
|
47
52
|
def log(level, message, context = {})
|
48
53
|
entry = {
|
49
54
|
timestamp: Time.now.utc.iso8601,
|
@@ -55,7 +60,7 @@ module Kscript
|
|
55
60
|
@logger.send(level, entry.to_json)
|
56
61
|
end
|
57
62
|
|
58
|
-
#
|
63
|
+
# 终端输出(带颜色、trace、时间等)
|
59
64
|
def klog(level, message, context = {})
|
60
65
|
if human_output?
|
61
66
|
puts "[#{level.to_s.upcase}] #{message} #{context.map { |k, v| "#{k}=#{v}" }.join(' ')}".strip
|
@@ -72,7 +77,7 @@ module Kscript
|
|
72
77
|
end
|
73
78
|
end
|
74
79
|
|
75
|
-
#
|
80
|
+
# 便捷方法(info/warn/error/debug)
|
76
81
|
def kinfo(msg, ctx = {})
|
77
82
|
klog(:info, msg, ctx)
|
78
83
|
end
|
@@ -8,7 +8,7 @@
|
|
8
8
|
require 'kscript'
|
9
9
|
|
10
10
|
module Kscript
|
11
|
-
class
|
11
|
+
class KkApnicIpUtils < Base
|
12
12
|
attr_reader :country_sn, :cache_file
|
13
13
|
|
14
14
|
# Initialize class instance, set country code and cache file path
|
@@ -69,7 +69,7 @@ module Kscript
|
|
69
69
|
end
|
70
70
|
|
71
71
|
def self.usage
|
72
|
-
"kscript
|
72
|
+
"kscript apnic_ip CN\nkscript apnic_ip US"
|
73
73
|
end
|
74
74
|
|
75
75
|
def self.group
|
@@ -17,14 +17,14 @@ module Kscript
|
|
17
17
|
class KkAwsS3Utils < Base
|
18
18
|
# 初始化,支持所有参数通过 CLI 传递
|
19
19
|
def initialize(*args, **opts)
|
20
|
-
super
|
20
|
+
super
|
21
21
|
# 兼容 --file test.txt 以及 --file=test.txt
|
22
22
|
@file = opts[:file] || args[0]
|
23
|
-
@bucket = opts[:bucket] || args[1] || ENV
|
23
|
+
@bucket = opts[:bucket] || args[1] || ENV.fetch('AWS_BUCKET', nil)
|
24
24
|
@key = opts[:key] || args[2]
|
25
|
-
@region = opts[:region] || ENV
|
26
|
-
@access_key = opts[:access_key] || ENV
|
27
|
-
@secret_key = opts[:secret_key] || ENV
|
25
|
+
@region = opts[:region] || ENV.fetch('AWS_REGION', nil)
|
26
|
+
@access_key = opts[:access_key] || ENV.fetch('AWS_ACCESS_KEY_ID', nil)
|
27
|
+
@secret_key = opts[:secret_key] || ENV.fetch('AWS_SECRET_ACCESS_KEY', nil)
|
28
28
|
end
|
29
29
|
|
30
30
|
# 主入口
|
@@ -8,7 +8,7 @@
|
|
8
8
|
require 'kscript'
|
9
9
|
|
10
10
|
module Kscript
|
11
|
-
class
|
11
|
+
class KkElasticCertFingerUtils < Base
|
12
12
|
DEFAULT_CERT_PATH = 'elasticsearch.crt'
|
13
13
|
|
14
14
|
attr_reader :cert_path
|
@@ -16,7 +16,7 @@ module Kscript
|
|
16
16
|
# Initialize with certificate path
|
17
17
|
# @param cert_path [String] path to the certificate file
|
18
18
|
def initialize(*args, **opts)
|
19
|
-
super
|
19
|
+
super
|
20
20
|
@cert_path = opts[:cert_path] || self.class::DEFAULT_CERT_PATH
|
21
21
|
end
|
22
22
|
|
@@ -31,7 +31,7 @@ module Kscript
|
|
31
31
|
end
|
32
32
|
|
33
33
|
def self.usage
|
34
|
-
"kscript
|
34
|
+
"kscript elastic_cert_finger <cert_file>\nkscript elastic_cert_finger ./ca.crt"
|
35
35
|
end
|
36
36
|
|
37
37
|
def self.group
|
@@ -8,9 +8,9 @@
|
|
8
8
|
require 'kscript'
|
9
9
|
|
10
10
|
module Kscript
|
11
|
-
class
|
11
|
+
class KkFfmpegInstallUtils < Base
|
12
12
|
def initialize(*args, **opts)
|
13
|
-
super
|
13
|
+
super
|
14
14
|
end
|
15
15
|
|
16
16
|
def run
|
@@ -28,7 +28,7 @@ module Kscript
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def self.usage
|
31
|
-
"kscript
|
31
|
+
"kscript ffmpeg_install 6.0\nkscript ffmpeg_install latest"
|
32
32
|
end
|
33
33
|
|
34
34
|
def self.group
|
@@ -8,11 +8,11 @@
|
|
8
8
|
require 'kscript'
|
9
9
|
|
10
10
|
module Kscript
|
11
|
-
class
|
11
|
+
class KkFileRenameUtils < Base
|
12
12
|
attr_reader :source_pattern, :target_pattern, :directory
|
13
13
|
|
14
14
|
def initialize(*args, **opts)
|
15
|
-
super
|
15
|
+
super
|
16
16
|
@source_pattern = args[0]
|
17
17
|
@target_pattern = args[1]
|
18
18
|
@directory = args[2] || Dir.pwd
|
@@ -35,7 +35,7 @@ module Kscript
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def self.usage
|
38
|
-
"kscript
|
38
|
+
"kscript file_rename foo bar ./src\nkscript file_rename 'test' 'prod' ~/projects"
|
39
39
|
end
|
40
40
|
|
41
41
|
def self.group
|
@@ -8,20 +8,23 @@
|
|
8
8
|
require 'kscript'
|
9
9
|
|
10
10
|
module Kscript
|
11
|
-
class
|
11
|
+
class KkIpLookupUtils < Base
|
12
12
|
IP_API_BASE_URL = 'http://ip-api.com/json'
|
13
13
|
IP_CHECK_URL = 'https://api.ipify.org?format=json'
|
14
14
|
|
15
15
|
attr_reader :ip_address
|
16
16
|
|
17
17
|
def initialize(*args, **opts)
|
18
|
-
super
|
18
|
+
super
|
19
19
|
@ip_address = args.first || fetch_public_ip
|
20
20
|
end
|
21
21
|
|
22
|
-
def run
|
22
|
+
def run(*args, **_opts)
|
23
23
|
with_error_handling do
|
24
|
-
|
24
|
+
ip = args.first || @ip_address
|
25
|
+
validate_ip_address!(ip)
|
26
|
+
response = make_api_request(ip)
|
27
|
+
handle_response(response)
|
25
28
|
end
|
26
29
|
end
|
27
30
|
|
@@ -36,7 +39,7 @@ module Kscript
|
|
36
39
|
end
|
37
40
|
|
38
41
|
def self.usage
|
39
|
-
"kscript
|
42
|
+
"kscript ip_lookup <ip_address>\nkscript ip_lookup 8.8.8.8"
|
40
43
|
end
|
41
44
|
|
42
45
|
def self.group
|
@@ -54,31 +57,43 @@ module Kscript
|
|
54
57
|
private
|
55
58
|
|
56
59
|
def fetch_public_ip
|
57
|
-
|
58
|
-
|
60
|
+
begin
|
61
|
+
require 'httpx'
|
62
|
+
rescue LoadError
|
63
|
+
abort 'Missing dependency: httpx. Please run: gem install httpx'
|
64
|
+
end
|
65
|
+
response = HTTPX.get(IP_CHECK_URL)
|
66
|
+
response = response.first if response.is_a?(Array)
|
67
|
+
raise "Failed to detect public IP: #{response.status}" unless response.status == 200
|
59
68
|
|
60
69
|
data = JSON.parse(response.body.to_s)
|
61
|
-
logger.
|
70
|
+
logger.kinfo("Detected public IP: #{data['ip']}")
|
62
71
|
data['ip']
|
63
72
|
end
|
64
73
|
|
65
|
-
def validate_ip_address!
|
66
|
-
return if valid_ip_format?
|
74
|
+
def validate_ip_address!(ip)
|
75
|
+
return if valid_ip_format?(ip)
|
67
76
|
|
68
77
|
raise ArgumentError, 'Invalid IP address format'
|
69
78
|
end
|
70
79
|
|
71
|
-
def valid_ip_format?
|
72
|
-
/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.match?(
|
80
|
+
def valid_ip_format?(ip)
|
81
|
+
/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.match?(ip)
|
73
82
|
end
|
74
83
|
|
75
|
-
def make_api_request
|
76
|
-
|
84
|
+
def make_api_request(ip)
|
85
|
+
begin
|
86
|
+
require 'httpx'
|
87
|
+
rescue LoadError
|
88
|
+
abort 'Missing dependency: httpx. Please run: gem install httpx'
|
89
|
+
end
|
90
|
+
response = HTTPX.get("#{IP_API_BASE_URL}/#{ip}")
|
91
|
+
response.is_a?(Array) ? response.first : response
|
77
92
|
end
|
78
93
|
|
79
94
|
def handle_response(response)
|
80
|
-
if response.status
|
81
|
-
logger.kinfo('IP location result', data:
|
95
|
+
if response.status == 200
|
96
|
+
logger.kinfo('IP location result', data: JSON.parse(response.body.to_s))
|
82
97
|
else
|
83
98
|
logger.kerror("API request failed: #{response.status}")
|
84
99
|
end
|
@@ -8,9 +8,9 @@
|
|
8
8
|
require 'kscript'
|
9
9
|
|
10
10
|
module Kscript
|
11
|
-
class
|
11
|
+
class KkJenkinsManageUtils < Base
|
12
12
|
def initialize(*args, **opts)
|
13
|
-
super
|
13
|
+
super
|
14
14
|
jenkins_url, user, password = args
|
15
15
|
@jenkins_url = jenkins_url
|
16
16
|
@user = user
|
@@ -106,7 +106,7 @@ module Kscript
|
|
106
106
|
end
|
107
107
|
|
108
108
|
def self.usage
|
109
|
-
"kscript
|
109
|
+
"kscript jenkins_manage list --host=jenkins.local\nkscript jenkins_manage trigger --job=build"
|
110
110
|
end
|
111
111
|
|
112
112
|
def self.group
|
@@ -8,9 +8,9 @@
|
|
8
8
|
require 'kscript'
|
9
9
|
|
10
10
|
module Kscript
|
11
|
-
class
|
11
|
+
class KkKibanaManageUtils < Base
|
12
12
|
def initialize(*args, **opts)
|
13
|
-
super
|
13
|
+
super
|
14
14
|
project_name, project_env, base_url, username, password = args
|
15
15
|
@base_url = base_url
|
16
16
|
@username = username
|
@@ -158,7 +158,7 @@ module Kscript
|
|
158
158
|
end
|
159
159
|
|
160
160
|
def self.usage
|
161
|
-
"kscript
|
161
|
+
"kscript kibana_manage export --host=localhost --index=log-*\nkscript kibana_manage import --file=dashboard.json"
|
162
162
|
end
|
163
163
|
|
164
164
|
def self.group
|
@@ -191,23 +191,23 @@ module Kscript
|
|
191
191
|
# Construct the body for creating an index
|
192
192
|
def index_body(index_name, uuid)
|
193
193
|
{
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
194
|
+
contentTypeId: 'index-pattern',
|
195
|
+
data: {
|
196
|
+
fieldAttrs: '{}',
|
197
|
+
title: "#{index_name}*",
|
198
|
+
timeFieldName: '@timestamp',
|
199
|
+
sourceFilters: '[]',
|
200
|
+
fields: '[]',
|
201
|
+
fieldFormatMap: '{}',
|
202
|
+
runtimeFieldMap: '{}',
|
203
|
+
name: index_name,
|
204
|
+
allowHidden: false
|
205
205
|
},
|
206
|
-
|
207
|
-
|
208
|
-
|
206
|
+
options: {
|
207
|
+
id: uuid,
|
208
|
+
overwrite: false
|
209
209
|
},
|
210
|
-
|
210
|
+
version: 1
|
211
211
|
}
|
212
212
|
end
|
213
213
|
|
@@ -8,7 +8,7 @@
|
|
8
8
|
require 'kscript'
|
9
9
|
|
10
10
|
module Kscript
|
11
|
-
class
|
11
|
+
class KkLvmManageUtils < Base
|
12
12
|
DEFAULT_CONFIG = {
|
13
13
|
device: '/dev/sdb',
|
14
14
|
volume_group: 'vg_data',
|
@@ -21,7 +21,7 @@ module Kscript
|
|
21
21
|
# Initialize the LVM mounter with configuration
|
22
22
|
# @param config [Hash] configuration options
|
23
23
|
def initialize(*args, **opts)
|
24
|
-
super
|
24
|
+
super
|
25
25
|
@config = DEFAULT_CONFIG.merge(opts)
|
26
26
|
end
|
27
27
|
|
@@ -47,7 +47,7 @@ module Kscript
|
|
47
47
|
end
|
48
48
|
|
49
49
|
def self.usage
|
50
|
-
"kscript
|
50
|
+
"kscript lvm_manage /dev/sda2 /mnt/data\nkscript lvm_manage /dev/vg0/lv_home /mnt/home"
|
51
51
|
end
|
52
52
|
|
53
53
|
def self.group
|
@@ -8,9 +8,9 @@
|
|
8
8
|
require 'kscript'
|
9
9
|
|
10
10
|
module Kscript
|
11
|
-
class
|
11
|
+
class KkMacOptimizeUtils < Base
|
12
12
|
def initialize(*args, **opts)
|
13
|
-
super
|
13
|
+
super
|
14
14
|
end
|
15
15
|
|
16
16
|
def run(*args, **_opts)
|
@@ -74,7 +74,7 @@ module Kscript
|
|
74
74
|
end
|
75
75
|
|
76
76
|
def self.usage
|
77
|
-
'kscript
|
77
|
+
'kscript mac_optimize'
|
78
78
|
end
|
79
79
|
|
80
80
|
def self.group
|
@@ -8,9 +8,9 @@
|
|
8
8
|
require 'kscript'
|
9
9
|
|
10
10
|
module Kscript
|
11
|
-
class
|
11
|
+
class KkMacStatusUtils < Base
|
12
12
|
def initialize(*_args, **opts)
|
13
|
-
super(**opts.merge(service: '
|
13
|
+
super(**opts.merge(service: 'kk_mac_status'))
|
14
14
|
end
|
15
15
|
|
16
16
|
def run
|
@@ -24,19 +24,12 @@ module Kscript
|
|
24
24
|
logger.kinfo("📅 Date Time: #{Time.now}")
|
25
25
|
logger.kinfo('')
|
26
26
|
|
27
|
-
# CPU
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
# Memory Usage
|
35
|
-
logger.kinfo('===============================')
|
36
|
-
logger.kinfo(' Memory Usage (Top 10)')
|
37
|
-
logger.kinfo('===============================')
|
38
|
-
mem_output = `ps aux | sort -nrk 4 | head -n 10`
|
39
|
-
logger.kinfo(mem_output)
|
27
|
+
# Top 10 by CPU
|
28
|
+
print_header('Top 10 Processes by CPU Usage')
|
29
|
+
print_process_list(:cpu)
|
30
|
+
# Top 10 by Memory
|
31
|
+
print_header('Top 10 Processes by Memory Usage')
|
32
|
+
print_process_list(:mem)
|
40
33
|
|
41
34
|
# GPU Usage
|
42
35
|
if `which powermetrics`.strip.empty?
|
@@ -77,6 +70,25 @@ module Kscript
|
|
77
70
|
logger.kinfo("\n✅ System resource check completed!")
|
78
71
|
end
|
79
72
|
|
73
|
+
def print_header(title)
|
74
|
+
logger.kinfo('')
|
75
|
+
logger.kinfo('===============================')
|
76
|
+
logger.kinfo(" #{title}")
|
77
|
+
logger.kinfo('===============================')
|
78
|
+
end
|
79
|
+
|
80
|
+
def print_process_list(sort_field)
|
81
|
+
lines = `ps aux`.split("\n")
|
82
|
+
lines.shift
|
83
|
+
processes = lines.map { |line| line.split(/\s+/, 11) }
|
84
|
+
index = sort_field == :cpu ? 2 : 3
|
85
|
+
top = processes.sort_by { |p| -p[index].to_f }.first(10)
|
86
|
+
logger.kinfo('USER PID %CPU %MEM COMMAND ')
|
87
|
+
top.each do |p|
|
88
|
+
logger.kinfo(format('%-10s %-8s %-5s %-5s %-10s', p[0], p[1], p[2], p[3], p[10][0..30]))
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
80
92
|
def self.description
|
81
93
|
'Show macOS system resource monitor report.'
|
82
94
|
end
|
@@ -86,7 +98,7 @@ module Kscript
|
|
86
98
|
end
|
87
99
|
|
88
100
|
def self.usage
|
89
|
-
"kscript
|
101
|
+
"kscript mac_status\nkscript mac_status --detail"
|
90
102
|
end
|
91
103
|
|
92
104
|
def self.group
|
@@ -8,7 +8,7 @@
|
|
8
8
|
require 'kscript'
|
9
9
|
|
10
10
|
module Kscript
|
11
|
-
class
|
11
|
+
class KkPortScanUtils < Base
|
12
12
|
attr_reader :host, :ports, :thread_count
|
13
13
|
|
14
14
|
# Initialize the scanner with target host and port range
|
@@ -16,7 +16,7 @@ module Kscript
|
|
16
16
|
# @param ports [Array<Integer>] list of ports to scan
|
17
17
|
# @param thread_count [Integer] number of concurrent threads
|
18
18
|
def initialize(*args, **opts)
|
19
|
-
super
|
19
|
+
super
|
20
20
|
@target = args[0]
|
21
21
|
@ports = parse_ports(args[1] || (1..1024))
|
22
22
|
@thread_count = (opts[:thread_count] || 50).to_i
|
@@ -98,7 +98,7 @@ module Kscript
|
|
98
98
|
end
|
99
99
|
|
100
100
|
def self.usage
|
101
|
-
"kscript
|
101
|
+
"kscript port_scan 192.168.1.1\nkscript port_scan example.com 22,80,443 100\nkscript port_scan 192.168.1.1 1..1024 200"
|
102
102
|
end
|
103
103
|
|
104
104
|
def self.group
|
@@ -8,9 +8,9 @@
|
|
8
8
|
require 'kscript'
|
9
9
|
|
10
10
|
module Kscript
|
11
|
-
class
|
11
|
+
class KkProjectScanUtils < Base
|
12
12
|
def initialize(*args, **opts)
|
13
|
-
super
|
13
|
+
super
|
14
14
|
end
|
15
15
|
|
16
16
|
def run
|
@@ -34,7 +34,7 @@ module Kscript
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def self.usage
|
37
|
-
"kscript
|
37
|
+
"kscript project_scan ~/projects/src\nkscript project_scan /opt --type=go"
|
38
38
|
end
|
39
39
|
|
40
40
|
def self.group
|
@@ -56,7 +56,7 @@ module Kscript
|
|
56
56
|
|
57
57
|
def scan_projects
|
58
58
|
projects = []
|
59
|
-
Dir.glob(File.join(@src_path, '*')).
|
59
|
+
Dir.glob(File.join(@src_path, '*')).each do |path|
|
60
60
|
next unless File.directory?(path)
|
61
61
|
next unless git_project?(path)
|
62
62
|
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (c) 2025 Kk
|
4
|
+
#
|
5
|
+
# This software is released under the MIT License.
|
6
|
+
# https://opensource.org/licenses/MIT
|
7
|
+
|
8
|
+
require 'kscript'
|
9
|
+
|
10
|
+
module Kscript
|
11
|
+
class KkShellHelperUtils < Base
|
12
|
+
CHT_SH_URL = 'https://cht.sh'
|
13
|
+
|
14
|
+
attr_reader :command
|
15
|
+
|
16
|
+
# Initialize with shell command to look up
|
17
|
+
# @param command [String] command to get help for
|
18
|
+
def initialize(*args, **opts)
|
19
|
+
super
|
20
|
+
@command = args.join(' ').strip
|
21
|
+
end
|
22
|
+
|
23
|
+
def run(*args, **_opts)
|
24
|
+
command = args.join(' ').strip
|
25
|
+
with_error_handling do
|
26
|
+
if command.nil? || command.strip.empty?
|
27
|
+
logger.kwarn("Usage: #{self.class.usage}")
|
28
|
+
else
|
29
|
+
fetch_help(command)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def help
|
35
|
+
if command
|
36
|
+
fetch_help
|
37
|
+
else
|
38
|
+
logger.kinfo("Usage: #{$PROGRAM_NAME} <command>")
|
39
|
+
exit 1
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# Fetch and display command documentation
|
44
|
+
def fetch_help(command)
|
45
|
+
response = make_request(command)
|
46
|
+
response = response.first if response.is_a?(Array)
|
47
|
+
puts response.body
|
48
|
+
rescue StandardError => e
|
49
|
+
display_error(e)
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.arguments
|
53
|
+
'[subcommand] [args...]'
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.usage
|
57
|
+
"kscript shell_helper 'ls'\nkscript shell_helper 'echo hello'"
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.group
|
61
|
+
'system'
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.author
|
65
|
+
'kk'
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.description
|
69
|
+
'Query shell command usage and cheatsheets.'
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
# Make HTTP request to cheat.sh
|
75
|
+
# @return [HTTPX::Response] response from cheat.sh
|
76
|
+
def make_request(command)
|
77
|
+
begin
|
78
|
+
require 'httpx'
|
79
|
+
require 'uri'
|
80
|
+
rescue LoadError
|
81
|
+
abort 'Missing dependency: httpx. Please run: gem install httpx'
|
82
|
+
end
|
83
|
+
HTTPX.with(
|
84
|
+
headers: {
|
85
|
+
'User-Agent' => 'curl/8.0.1',
|
86
|
+
'Accept' => 'text/plain'
|
87
|
+
}
|
88
|
+
).get("https://cheat.sh/#{URI.encode_www_form_component(command)}")
|
89
|
+
end
|
90
|
+
|
91
|
+
# Display error message
|
92
|
+
# @param error [StandardError] error to display
|
93
|
+
def display_error(error)
|
94
|
+
logger.kerror("An error occurred: #{error.message}")
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -11,7 +11,7 @@ require 'net/http'
|
|
11
11
|
require 'json'
|
12
12
|
|
13
13
|
module Kscript
|
14
|
-
class
|
14
|
+
class KkUsdRateUtils < Base
|
15
15
|
API_URL = 'https://api.exchangerate-api.com/v4/latest/USD'
|
16
16
|
|
17
17
|
def initialize(currency_code = 'CNY', *args, **opts)
|
@@ -44,7 +44,7 @@ module Kscript
|
|
44
44
|
end
|
45
45
|
|
46
46
|
def self.usage
|
47
|
-
"kscript
|
47
|
+
"kscript usd_rate CNY\nkscript usd_rate EUR"
|
48
48
|
end
|
49
49
|
|
50
50
|
def self.group
|
@@ -8,7 +8,7 @@
|
|
8
8
|
require 'kscript'
|
9
9
|
|
10
10
|
module Kscript
|
11
|
-
class
|
11
|
+
class KkVcsCleanerUtils < Base
|
12
12
|
DEFAULT_RETAIN_VERSIONS = 10
|
13
13
|
|
14
14
|
attr_reader :source_path, :retain_count
|
@@ -17,7 +17,7 @@ module Kscript
|
|
17
17
|
# @param source_path [String] path to source code directory
|
18
18
|
# @param retain_count [Integer] number of versions to keep
|
19
19
|
def initialize(*args, **opts)
|
20
|
-
super
|
20
|
+
super
|
21
21
|
@source_path = args[0] || '/data/sources/*/**'
|
22
22
|
@retain_count = args[1] || DEFAULT_RETAIN_VERSIONS
|
23
23
|
end
|
@@ -40,7 +40,7 @@ module Kscript
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def self.usage
|
43
|
-
"kscript
|
43
|
+
"kscript vcs_cleaner ~/projects/src\nkscript vcs_cleaner . --exclude=vendor"
|
44
44
|
end
|
45
45
|
|
46
46
|
def self.group
|
data/lib/kscript/plugins.rb
CHANGED
@@ -5,7 +5,7 @@ module Kscript
|
|
5
5
|
PLUGIN_DIR = File.expand_path('plugins', __dir__)
|
6
6
|
|
7
7
|
def self.load_all
|
8
|
-
Dir.glob(File.join(PLUGIN_DIR, 'kk_*.rb')).
|
8
|
+
Dir.glob(File.join(PLUGIN_DIR, 'kk_*.rb')).each do |file|
|
9
9
|
# 解析出类名
|
10
10
|
basename = File.basename(file, '.rb')
|
11
11
|
class_name = basename.split('_').map(&:capitalize).join
|
data/lib/kscript/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kscript
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kk
|
@@ -59,25 +59,19 @@ dependencies:
|
|
59
59
|
- !ruby/object:Gem::Version
|
60
60
|
version: '3.0'
|
61
61
|
- !ruby/object:Gem::Dependency
|
62
|
-
name:
|
62
|
+
name: httpx
|
63
63
|
requirement: !ruby/object:Gem::Requirement
|
64
64
|
requirements:
|
65
|
-
- - "
|
66
|
-
- !ruby/object:Gem::Version
|
67
|
-
version: '4.0'
|
68
|
-
- - "<"
|
65
|
+
- - "~>"
|
69
66
|
- !ruby/object:Gem::Version
|
70
|
-
version: '
|
67
|
+
version: '1.5'
|
71
68
|
type: :runtime
|
72
69
|
prerelease: false
|
73
70
|
version_requirements: !ruby/object:Gem::Requirement
|
74
71
|
requirements:
|
75
|
-
- - "
|
76
|
-
- !ruby/object:Gem::Version
|
77
|
-
version: '4.0'
|
78
|
-
- - "<"
|
72
|
+
- - "~>"
|
79
73
|
- !ruby/object:Gem::Version
|
80
|
-
version: '
|
74
|
+
version: '1.5'
|
81
75
|
- !ruby/object:Gem::Dependency
|
82
76
|
name: nokogiri
|
83
77
|
requirement: !ruby/object:Gem::Requirement
|
@@ -162,23 +156,22 @@ files:
|
|
162
156
|
- lib/kscript/config.rb
|
163
157
|
- lib/kscript/logger.rb
|
164
158
|
- lib/kscript/plugins.rb
|
165
|
-
- lib/kscript/plugins/
|
159
|
+
- lib/kscript/plugins/kk_apnic_ip_utils.rb
|
166
160
|
- lib/kscript/plugins/kk_aws_s3_utils.rb
|
167
|
-
- lib/kscript/plugins/
|
168
|
-
- lib/kscript/plugins/
|
169
|
-
- lib/kscript/plugins/
|
170
|
-
- lib/kscript/plugins/
|
171
|
-
- lib/kscript/plugins/
|
172
|
-
- lib/kscript/plugins/
|
173
|
-
- lib/kscript/plugins/
|
174
|
-
- lib/kscript/plugins/
|
175
|
-
- lib/kscript/plugins/
|
176
|
-
- lib/kscript/plugins/
|
177
|
-
- lib/kscript/plugins/
|
178
|
-
- lib/kscript/plugins/
|
179
|
-
- lib/kscript/plugins/
|
180
|
-
- lib/kscript/plugins/
|
181
|
-
- lib/kscript/plugins/kk_usd_utils.rb
|
161
|
+
- lib/kscript/plugins/kk_elastic_cert_finger_utils.rb
|
162
|
+
- lib/kscript/plugins/kk_ffmpeg_install_utils.rb
|
163
|
+
- lib/kscript/plugins/kk_file_rename_utils.rb
|
164
|
+
- lib/kscript/plugins/kk_ip_lookup_utils.rb
|
165
|
+
- lib/kscript/plugins/kk_jenkins_manage_utils.rb
|
166
|
+
- lib/kscript/plugins/kk_kibana_manage_utils.rb
|
167
|
+
- lib/kscript/plugins/kk_lvm_manage_utils.rb
|
168
|
+
- lib/kscript/plugins/kk_mac_optimize_utils.rb
|
169
|
+
- lib/kscript/plugins/kk_mac_status_utils.rb
|
170
|
+
- lib/kscript/plugins/kk_port_scan_utils.rb
|
171
|
+
- lib/kscript/plugins/kk_project_scan_utils.rb
|
172
|
+
- lib/kscript/plugins/kk_shell_helper_utils.rb
|
173
|
+
- lib/kscript/plugins/kk_usd_rate_utils.rb
|
174
|
+
- lib/kscript/plugins/kk_vcs_cleaner_utils.rb
|
182
175
|
- lib/kscript/plugins/kk_wg_acl_utils.rb
|
183
176
|
- lib/kscript/plugins/kk_wg_pass_utils.rb
|
184
177
|
- lib/kscript/post_install.rb
|
@@ -1,111 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# Copyright (c) 2025 Kk
|
4
|
-
#
|
5
|
-
# This software is released under the MIT License.
|
6
|
-
# https://opensource.org/licenses/MIT
|
7
|
-
|
8
|
-
require 'kscript'
|
9
|
-
|
10
|
-
module Kscript
|
11
|
-
class KkShUtils < Base
|
12
|
-
CHT_SH_URL = 'https://cht.sh'
|
13
|
-
|
14
|
-
attr_reader :command
|
15
|
-
|
16
|
-
# Initialize with shell command to look up
|
17
|
-
# @param command [String] command to get help for
|
18
|
-
def initialize(*args, **opts)
|
19
|
-
super(*args, **opts)
|
20
|
-
@command = args.first
|
21
|
-
end
|
22
|
-
|
23
|
-
def run
|
24
|
-
with_error_handling do
|
25
|
-
help
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def help
|
30
|
-
if command
|
31
|
-
fetch_help
|
32
|
-
else
|
33
|
-
logger.kinfo("Usage: #{$PROGRAM_NAME} <command>")
|
34
|
-
exit 1
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
# Fetch and display command documentation
|
39
|
-
def fetch_help
|
40
|
-
response = make_request
|
41
|
-
display_result(response)
|
42
|
-
rescue HTTP::Error => e
|
43
|
-
display_error(e)
|
44
|
-
end
|
45
|
-
|
46
|
-
def self.arguments
|
47
|
-
'[subcommand] [args...]'
|
48
|
-
end
|
49
|
-
|
50
|
-
def self.usage
|
51
|
-
"kscript sh 'ls'\nkscript sh 'echo hello'"
|
52
|
-
end
|
53
|
-
|
54
|
-
def self.group
|
55
|
-
'system'
|
56
|
-
end
|
57
|
-
|
58
|
-
def self.author
|
59
|
-
'kk'
|
60
|
-
end
|
61
|
-
|
62
|
-
def self.description
|
63
|
-
'Query sh command usage and cheatsheets.'
|
64
|
-
end
|
65
|
-
|
66
|
-
private
|
67
|
-
|
68
|
-
# Make HTTP request to cht.sh
|
69
|
-
# @return [HTTP::Response] response from cht.sh
|
70
|
-
def make_request
|
71
|
-
HTTP.get("#{CHT_SH_URL}/#{command}")
|
72
|
-
end
|
73
|
-
|
74
|
-
# Display command documentation
|
75
|
-
# @param response [HTTP::Response] response from cht.sh
|
76
|
-
def display_result(response)
|
77
|
-
if response.status.success?
|
78
|
-
text = extract_plain_text(response.body)
|
79
|
-
logger.kinfo(text)
|
80
|
-
else
|
81
|
-
logger.kerror("Failed to retrieve data: #{response.status}")
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
# 提取纯文本内容
|
86
|
-
def extract_plain_text(body)
|
87
|
-
body = body.to_s
|
88
|
-
begin
|
89
|
-
doc = Nokogiri::HTML(body)
|
90
|
-
doc.search('script,style').remove
|
91
|
-
text = doc.text.lines.map(&:strip)
|
92
|
-
# 过滤掉包含广告/社交/Follow等内容的行
|
93
|
-
text = text.reject { |line| line =~ /Follow @|twitter|github|sponsor|donate|chubin|^!function/ }
|
94
|
-
text.reject!(&:empty?)
|
95
|
-
# 去除顶部多余空白行,只保留正文
|
96
|
-
text = text.drop_while(&:empty?)
|
97
|
-
text.join("\n")
|
98
|
-
rescue StandardError
|
99
|
-
body.gsub(/\e\[[\d;]*m/, '').lines.reject do |line|
|
100
|
-
line =~ /Follow @|twitter|github|sponsor|donate|chubin|^!function/
|
101
|
-
end.drop_while { |line| line.strip.empty? }.join
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
# Display error message
|
106
|
-
# @param error [StandardError] error to display
|
107
|
-
def display_error(error)
|
108
|
-
logger.kerror("An error occurred: #{error.message}")
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
@@ -1,71 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# Copyright (c) 2025 Kk
|
4
|
-
#
|
5
|
-
# This software is released under the MIT License.
|
6
|
-
# https://opensource.org/licenses/MIT
|
7
|
-
|
8
|
-
require 'kscript'
|
9
|
-
|
10
|
-
module Kscript
|
11
|
-
class KkTopUtils < Base
|
12
|
-
def initialize(*args, **opts)
|
13
|
-
super(*args, **opts)
|
14
|
-
end
|
15
|
-
|
16
|
-
def run
|
17
|
-
with_error_handling do
|
18
|
-
print_report
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
def print_report
|
23
|
-
logger.kinfo("System Resource Top Report - #{Time.now.strftime('%Y-%m-%d %H:%M:%S')}")
|
24
|
-
print_header('Top 10 Processes by CPU Usage')
|
25
|
-
print_process_list(:cpu)
|
26
|
-
print_header('Top 10 Processes by Memory Usage')
|
27
|
-
print_process_list(:mem)
|
28
|
-
end
|
29
|
-
|
30
|
-
def print_header(title)
|
31
|
-
logger.kinfo('')
|
32
|
-
logger.kinfo('===============================')
|
33
|
-
logger.kinfo(" #{title}")
|
34
|
-
logger.kinfo('===============================')
|
35
|
-
end
|
36
|
-
|
37
|
-
def print_process_list(sort_field)
|
38
|
-
lines = `ps aux`.split("\n")
|
39
|
-
lines.shift
|
40
|
-
processes = lines.map { |line| line.split(/\s+/, 11) }
|
41
|
-
index = sort_field == :cpu ? 2 : 3
|
42
|
-
top = processes.sort_by { |p| -p[index].to_f }.first(10)
|
43
|
-
logger.kinfo(format('%-10s %-8s %-5s %-5s %-10s', 'USER', 'PID', '%CPU', '%MEM', 'COMMAND'))
|
44
|
-
top.each do |p|
|
45
|
-
logger.kinfo(format('%-10s %-8s %-5s %-5s %-10s', p[0], p[1], p[2], p[3], p[10][0..30]))
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def self.description
|
50
|
-
'Show top 10 processes by CPU/memory on macOS.'
|
51
|
-
end
|
52
|
-
|
53
|
-
def self.arguments
|
54
|
-
''
|
55
|
-
end
|
56
|
-
|
57
|
-
def self.usage
|
58
|
-
'kscript top'
|
59
|
-
end
|
60
|
-
|
61
|
-
def self.group
|
62
|
-
'macos'
|
63
|
-
end
|
64
|
-
|
65
|
-
def self.author
|
66
|
-
'kk'
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
Kscript::KkTopUtils.new.run if __FILE__ == $PROGRAM_NAME
|