diff --git a/lib/data/model/app/shell_func.dart b/lib/data/model/app/shell_func.dart index c67a5543..64cf7ea9 100644 --- a/lib/data/model/app/shell_func.dart +++ b/lib/data/model/app/shell_func.dart @@ -1,22 +1,46 @@ import '../../res/server_cmd.dart'; -class AppShellFunc { - final String name; - final String cmd; - final String flag; +const _cmdDivider = '\necho $seperator\n'; - const AppShellFunc(this.name, this.cmd, this.flag); +enum AppShellFuncType { + status, + docker; + + String get flag { + switch (this) { + case AppShellFuncType.status: + return 's'; + case AppShellFuncType.docker: + return 'd'; + } + } String get exec => 'sh $shellPath -$flag'; -} -typedef AppShellFuncs = List; + String get name { + switch (this) { + case AppShellFuncType.status: + return 'status'; + case AppShellFuncType.docker: + /// `dockeR` -> avoid conflict with `docker` command + /// 以防止循环递归 + return 'dockeR'; + } + } -extension AppShellFuncsExt on AppShellFuncs { - String get generate { + String get cmd { + switch (this) { + case AppShellFuncType.status: + return statusCmds.join(_cmdDivider); + case AppShellFuncType.docker: + return dockerCmds.join(_cmdDivider); + } + } + + static String get shellScript { final sb = StringBuffer(); // Write each func - for (final func in this) { + for (final func in values) { sb.write(''' ${func.name}() { ${func.cmd} @@ -27,7 +51,7 @@ ${func.cmd} // Write switch case sb.write('case \$1 in\n'); - for (final func in this) { + for (final func in values) { sb.write(''' '-${func.flag}') ${func.name} @@ -38,13 +62,43 @@ ${func.cmd} *) echo "Invalid argument \$1" ;; -esac -'''); +esac'''); return sb.toString(); } } -// enum AppShellFuncType { -// status, -// docker; -// } +abstract class _CmdType { + /// Find out the required segment from [segments] + String find(List segments); +} + +enum StatusCmdType implements _CmdType { + net, + sys, + cpu, + uptime, + conn, + disk, + mem, + tempType, + tempVal, + host, + sysRhel; + + @override + String find(List segments) { + return segments[index]; + } +} + +enum DockerCmdType implements _CmdType { + version, + ps, + stats, + images; + + @override + String find(List segments) { + return segments[index]; + } +} diff --git a/lib/data/model/server/server_status_update_req.dart b/lib/data/model/server/server_status_update_req.dart index b75c4f7b..9337d0c9 100644 --- a/lib/data/model/server/server_status_update_req.dart +++ b/lib/data/model/server/server_status_update_req.dart @@ -1,4 +1,4 @@ -import '../../res/server_cmd.dart'; +import '../app/shell_func.dart'; import 'cpu.dart'; import 'disk.dart'; import 'memory.dart'; @@ -13,50 +13,43 @@ class ServerStatusUpdateReq { const ServerStatusUpdateReq(this.ss, this.segments); } -extension _SegmentsExt on List { - String at(CmdType t) { - final index = t.index; - if (index >= length) return ''; - return this[index]; - } -} - Future getStatus(ServerStatusUpdateReq req) async { - final net = parseNetSpeed(req.segments.at(CmdType.net)); + final segments = req.segments; + final net = parseNetSpeed(StatusCmdType.net.find(segments)); req.ss.netSpeed.update(net); final sys = _parseSysVer( - req.segments.at(CmdType.sys), - req.segments.at(CmdType.host), - req.segments.at(CmdType.sysRhel), + StatusCmdType.sys.find(segments), + StatusCmdType.host.find(segments), + StatusCmdType.sysRhel.find(segments), ); if (sys != null) { req.ss.sysVer = sys; } - final cpus = parseCPU(req.segments.at(CmdType.cpu)); + final cpus = parseCPU(StatusCmdType.cpu.find(segments)); req.ss.cpu.update(cpus); req.ss.temps.parse( - req.segments.at(CmdType.tempType), - req.segments.at(CmdType.tempVal), + StatusCmdType.tempType.find(segments), + StatusCmdType.tempVal.find(segments), ); - final tcp = parseConn(req.segments.at(CmdType.conn)); + final tcp = parseConn(StatusCmdType.conn.find(segments)); if (tcp != null) { req.ss.tcp = tcp; } - req.ss.disk = parseDisk(req.segments.at(CmdType.disk)); + req.ss.disk = parseDisk(StatusCmdType.disk.find(segments)); - req.ss.mem = parseMem(req.segments.at(CmdType.mem)); + req.ss.mem = parseMem(StatusCmdType.mem.find(segments)); - final uptime = _parseUpTime(req.segments.at(CmdType.uptime)); + final uptime = _parseUpTime(StatusCmdType.uptime.find(segments)); if (uptime != null) { req.ss.uptime = uptime; } - req.ss.swap = parseSwap(req.segments.at(CmdType.mem)); + req.ss.swap = parseSwap(StatusCmdType.mem.find(segments)); return req.ss; } diff --git a/lib/data/provider/docker.dart b/lib/data/provider/docker.dart index cb294755..391ab49d 100644 --- a/lib/data/provider/docker.dart +++ b/lib/data/provider/docker.dart @@ -6,6 +6,7 @@ import 'package:logging/logging.dart'; import 'package:toolbox/core/extension/ssh_client.dart'; import 'package:toolbox/core/extension/stringx.dart'; import 'package:toolbox/core/provider_base.dart'; +import 'package:toolbox/data/model/app/shell_func.dart'; import 'package:toolbox/data/model/docker/image.dart'; import 'package:toolbox/data/model/docker/ps.dart'; import 'package:toolbox/data/model/app/error.dart'; @@ -55,7 +56,7 @@ class DockerProvider extends BusyProvider { var raw = ''; await client!.exec( - shellFuncDocker.exec, + AppShellFuncType.docker.exec, onStderr: _onPwd, onStdout: (data, _) => raw = '$raw$data', ); @@ -75,7 +76,7 @@ class DockerProvider extends BusyProvider { } // Parse docker version - final verRaw = segments[0]; + final verRaw = DockerCmdType.version.find(segments); try { version = _versionReg.firstMatch(verRaw)?.group(2); edition = _editionReg.firstMatch(verRaw)?.group(2); @@ -88,7 +89,7 @@ class DockerProvider extends BusyProvider { } // Parse docker ps - final psRaw = segments[1]; + final psRaw = DockerCmdType.ps.find(segments); try { final lines = psRaw.split('\n'); lines.removeWhere((element) => element.isEmpty); @@ -105,7 +106,7 @@ class DockerProvider extends BusyProvider { } // Parse docker images - final imageRaw = segments[3]; + final imageRaw = DockerCmdType.images.find(segments); try { final imageLines = imageRaw.split('\n'); imageLines.removeWhere((element) => element.isEmpty); @@ -122,7 +123,7 @@ class DockerProvider extends BusyProvider { } // Parse docker stats - final statsRaw = segments[2]; + final statsRaw = DockerCmdType.stats.find(segments); try { final statsLines = statsRaw.split('\n'); statsLines.removeWhere((element) => element.isEmpty); diff --git a/lib/data/provider/server.dart b/lib/data/provider/server.dart index 62a2470c..4a612f72 100644 --- a/lib/data/provider/server.dart +++ b/lib/data/provider/server.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'package:flutter/foundation.dart'; import 'package:logging/logging.dart'; +import 'package:toolbox/data/model/app/shell_func.dart'; import '../../core/extension/order.dart'; import '../../core/extension/uint8list.dart'; @@ -245,9 +246,9 @@ class ServerProvider extends BusyProvider { if (s.client == null) return; // run script to get server status - raw = await s.client!.run(shellFuncStatus.exec).string; + raw = await s.client!.run(AppShellFuncType.status.exec).string; segments = raw.split(seperator).map((e) => e.trim()).toList(); - if (raw.isEmpty || segments.length != CmdType.values.length) { + if (raw.isEmpty || segments.length != StatusCmdType.values.length) { s.state = ServerState.failed; if (s.status.failedInfo?.isEmpty ?? true) { s.status.failedInfo = 'Seperate segments failed, raw:\n$raw'; diff --git a/lib/data/res/server_cmd.dart b/lib/data/res/server_cmd.dart index 35c41084..71f8b725 100644 --- a/lib/data/res/server_cmd.dart +++ b/lib/data/res/server_cmd.dart @@ -7,21 +7,7 @@ const shellPath = '$serverBoxDir/mobile_app.sh'; const echoPWD = 'echo \$PWD'; -enum CmdType { - net, - sys, - cpu, - uptime, - conn, - disk, - mem, - tempType, - tempVal, - host, - sysRhel, -} - -const _cmdList = [ +const statusCmds = [ 'cat /proc/net/dev && date +%s', 'cat /etc/os-release | grep PRETTY_NAME', 'cat /proc/stat | grep cpu', @@ -35,12 +21,6 @@ const _cmdList = [ 'cat /etc/redhat-release', ]; -final shellFuncStatus = AppShellFunc( - 'status', - _cmdList.join('\necho $seperator\n'), - 's', -); - const dockerCmds = [ 'docker version', 'docker ps -a', @@ -48,26 +28,13 @@ const dockerCmds = [ 'docker image ls', ]; -final shellFuncDocker = AppShellFunc( - // `dockeR` -> avoid conflict with `docker` command - // 以防止循环递归 - 'dockeR', - dockerCmds.join('\necho $seperator\n'), - 'd', -); - -final _generated = [ - shellFuncStatus, - shellFuncDocker, -].generate; - final shellCmd = """ # Script for app `${BuildData.name} v1.0.${BuildData.build}` # Delete this file while app is running will cause app crash export LANG=en_US.utf-8 -$_generated +${AppShellFuncType.shellScript} """; final installShellCmd = "mkdir -p $serverBoxDir && " diff --git a/lib/view/page/docker.dart b/lib/view/page/docker.dart index 1308c407..13d0cb5b 100644 --- a/lib/view/page/docker.dart +++ b/lib/view/page/docker.dart @@ -456,6 +456,8 @@ class _DockerManagePageState extends State { subtitle: Text(_buildSubtitle(_docker.items!), style: grey), ), ); + // Bottom padding + items.add(height13); return Column( mainAxisSize: MainAxisSize.min, children: items,