mirror of
https://github.com/lollipopkit/flutter_server_box.git
synced 2025-12-17 15:24:35 +01:00
opt.: refactor AppShellFunc
This commit is contained in:
@@ -1,22 +1,46 @@
|
|||||||
import '../../res/server_cmd.dart';
|
import '../../res/server_cmd.dart';
|
||||||
|
|
||||||
class AppShellFunc {
|
const _cmdDivider = '\necho $seperator\n';
|
||||||
final String name;
|
|
||||||
final String cmd;
|
|
||||||
final String flag;
|
|
||||||
|
|
||||||
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';
|
String get exec => 'sh $shellPath -$flag';
|
||||||
}
|
|
||||||
|
|
||||||
typedef AppShellFuncs = List<AppShellFunc>;
|
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 cmd {
|
||||||
String get generate {
|
switch (this) {
|
||||||
|
case AppShellFuncType.status:
|
||||||
|
return statusCmds.join(_cmdDivider);
|
||||||
|
case AppShellFuncType.docker:
|
||||||
|
return dockerCmds.join(_cmdDivider);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static String get shellScript {
|
||||||
final sb = StringBuffer();
|
final sb = StringBuffer();
|
||||||
// Write each func
|
// Write each func
|
||||||
for (final func in this) {
|
for (final func in values) {
|
||||||
sb.write('''
|
sb.write('''
|
||||||
${func.name}() {
|
${func.name}() {
|
||||||
${func.cmd}
|
${func.cmd}
|
||||||
@@ -27,7 +51,7 @@ ${func.cmd}
|
|||||||
|
|
||||||
// Write switch case
|
// Write switch case
|
||||||
sb.write('case \$1 in\n');
|
sb.write('case \$1 in\n');
|
||||||
for (final func in this) {
|
for (final func in values) {
|
||||||
sb.write('''
|
sb.write('''
|
||||||
'-${func.flag}')
|
'-${func.flag}')
|
||||||
${func.name}
|
${func.name}
|
||||||
@@ -38,13 +62,43 @@ ${func.cmd}
|
|||||||
*)
|
*)
|
||||||
echo "Invalid argument \$1"
|
echo "Invalid argument \$1"
|
||||||
;;
|
;;
|
||||||
esac
|
esac''');
|
||||||
''');
|
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// enum AppShellFuncType {
|
abstract class _CmdType {
|
||||||
// status,
|
/// Find out the required segment from [segments]
|
||||||
// docker;
|
String find(List<String> segments);
|
||||||
// }
|
}
|
||||||
|
|
||||||
|
enum StatusCmdType implements _CmdType {
|
||||||
|
net,
|
||||||
|
sys,
|
||||||
|
cpu,
|
||||||
|
uptime,
|
||||||
|
conn,
|
||||||
|
disk,
|
||||||
|
mem,
|
||||||
|
tempType,
|
||||||
|
tempVal,
|
||||||
|
host,
|
||||||
|
sysRhel;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String find(List<String> segments) {
|
||||||
|
return segments[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum DockerCmdType implements _CmdType {
|
||||||
|
version,
|
||||||
|
ps,
|
||||||
|
stats,
|
||||||
|
images;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String find(List<String> segments) {
|
||||||
|
return segments[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import '../../res/server_cmd.dart';
|
import '../app/shell_func.dart';
|
||||||
import 'cpu.dart';
|
import 'cpu.dart';
|
||||||
import 'disk.dart';
|
import 'disk.dart';
|
||||||
import 'memory.dart';
|
import 'memory.dart';
|
||||||
@@ -13,50 +13,43 @@ class ServerStatusUpdateReq {
|
|||||||
const ServerStatusUpdateReq(this.ss, this.segments);
|
const ServerStatusUpdateReq(this.ss, this.segments);
|
||||||
}
|
}
|
||||||
|
|
||||||
extension _SegmentsExt on List<String> {
|
|
||||||
String at(CmdType t) {
|
|
||||||
final index = t.index;
|
|
||||||
if (index >= length) return '';
|
|
||||||
return this[index];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<ServerStatus> getStatus(ServerStatusUpdateReq req) async {
|
Future<ServerStatus> 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);
|
req.ss.netSpeed.update(net);
|
||||||
|
|
||||||
final sys = _parseSysVer(
|
final sys = _parseSysVer(
|
||||||
req.segments.at(CmdType.sys),
|
StatusCmdType.sys.find(segments),
|
||||||
req.segments.at(CmdType.host),
|
StatusCmdType.host.find(segments),
|
||||||
req.segments.at(CmdType.sysRhel),
|
StatusCmdType.sysRhel.find(segments),
|
||||||
);
|
);
|
||||||
if (sys != null) {
|
if (sys != null) {
|
||||||
req.ss.sysVer = sys;
|
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.cpu.update(cpus);
|
||||||
|
|
||||||
req.ss.temps.parse(
|
req.ss.temps.parse(
|
||||||
req.segments.at(CmdType.tempType),
|
StatusCmdType.tempType.find(segments),
|
||||||
req.segments.at(CmdType.tempVal),
|
StatusCmdType.tempVal.find(segments),
|
||||||
);
|
);
|
||||||
|
|
||||||
final tcp = parseConn(req.segments.at(CmdType.conn));
|
final tcp = parseConn(StatusCmdType.conn.find(segments));
|
||||||
if (tcp != null) {
|
if (tcp != null) {
|
||||||
req.ss.tcp = tcp;
|
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) {
|
if (uptime != null) {
|
||||||
req.ss.uptime = uptime;
|
req.ss.uptime = uptime;
|
||||||
}
|
}
|
||||||
|
|
||||||
req.ss.swap = parseSwap(req.segments.at(CmdType.mem));
|
req.ss.swap = parseSwap(StatusCmdType.mem.find(segments));
|
||||||
return req.ss;
|
return req.ss;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import 'package:logging/logging.dart';
|
|||||||
import 'package:toolbox/core/extension/ssh_client.dart';
|
import 'package:toolbox/core/extension/ssh_client.dart';
|
||||||
import 'package:toolbox/core/extension/stringx.dart';
|
import 'package:toolbox/core/extension/stringx.dart';
|
||||||
import 'package:toolbox/core/provider_base.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/image.dart';
|
||||||
import 'package:toolbox/data/model/docker/ps.dart';
|
import 'package:toolbox/data/model/docker/ps.dart';
|
||||||
import 'package:toolbox/data/model/app/error.dart';
|
import 'package:toolbox/data/model/app/error.dart';
|
||||||
@@ -55,7 +56,7 @@ class DockerProvider extends BusyProvider {
|
|||||||
|
|
||||||
var raw = '';
|
var raw = '';
|
||||||
await client!.exec(
|
await client!.exec(
|
||||||
shellFuncDocker.exec,
|
AppShellFuncType.docker.exec,
|
||||||
onStderr: _onPwd,
|
onStderr: _onPwd,
|
||||||
onStdout: (data, _) => raw = '$raw$data',
|
onStdout: (data, _) => raw = '$raw$data',
|
||||||
);
|
);
|
||||||
@@ -75,7 +76,7 @@ class DockerProvider extends BusyProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Parse docker version
|
// Parse docker version
|
||||||
final verRaw = segments[0];
|
final verRaw = DockerCmdType.version.find(segments);
|
||||||
try {
|
try {
|
||||||
version = _versionReg.firstMatch(verRaw)?.group(2);
|
version = _versionReg.firstMatch(verRaw)?.group(2);
|
||||||
edition = _editionReg.firstMatch(verRaw)?.group(2);
|
edition = _editionReg.firstMatch(verRaw)?.group(2);
|
||||||
@@ -88,7 +89,7 @@ class DockerProvider extends BusyProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Parse docker ps
|
// Parse docker ps
|
||||||
final psRaw = segments[1];
|
final psRaw = DockerCmdType.ps.find(segments);
|
||||||
try {
|
try {
|
||||||
final lines = psRaw.split('\n');
|
final lines = psRaw.split('\n');
|
||||||
lines.removeWhere((element) => element.isEmpty);
|
lines.removeWhere((element) => element.isEmpty);
|
||||||
@@ -105,7 +106,7 @@ class DockerProvider extends BusyProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Parse docker images
|
// Parse docker images
|
||||||
final imageRaw = segments[3];
|
final imageRaw = DockerCmdType.images.find(segments);
|
||||||
try {
|
try {
|
||||||
final imageLines = imageRaw.split('\n');
|
final imageLines = imageRaw.split('\n');
|
||||||
imageLines.removeWhere((element) => element.isEmpty);
|
imageLines.removeWhere((element) => element.isEmpty);
|
||||||
@@ -122,7 +123,7 @@ class DockerProvider extends BusyProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Parse docker stats
|
// Parse docker stats
|
||||||
final statsRaw = segments[2];
|
final statsRaw = DockerCmdType.stats.find(segments);
|
||||||
try {
|
try {
|
||||||
final statsLines = statsRaw.split('\n');
|
final statsLines = statsRaw.split('\n');
|
||||||
statsLines.removeWhere((element) => element.isEmpty);
|
statsLines.removeWhere((element) => element.isEmpty);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import 'dart:async';
|
|||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
|
import 'package:toolbox/data/model/app/shell_func.dart';
|
||||||
|
|
||||||
import '../../core/extension/order.dart';
|
import '../../core/extension/order.dart';
|
||||||
import '../../core/extension/uint8list.dart';
|
import '../../core/extension/uint8list.dart';
|
||||||
@@ -245,9 +246,9 @@ class ServerProvider extends BusyProvider {
|
|||||||
|
|
||||||
if (s.client == null) return;
|
if (s.client == null) return;
|
||||||
// run script to get server status
|
// 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();
|
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;
|
s.state = ServerState.failed;
|
||||||
if (s.status.failedInfo?.isEmpty ?? true) {
|
if (s.status.failedInfo?.isEmpty ?? true) {
|
||||||
s.status.failedInfo = 'Seperate segments failed, raw:\n$raw';
|
s.status.failedInfo = 'Seperate segments failed, raw:\n$raw';
|
||||||
|
|||||||
@@ -7,21 +7,7 @@ const shellPath = '$serverBoxDir/mobile_app.sh';
|
|||||||
|
|
||||||
const echoPWD = 'echo \$PWD';
|
const echoPWD = 'echo \$PWD';
|
||||||
|
|
||||||
enum CmdType {
|
const statusCmds = [
|
||||||
net,
|
|
||||||
sys,
|
|
||||||
cpu,
|
|
||||||
uptime,
|
|
||||||
conn,
|
|
||||||
disk,
|
|
||||||
mem,
|
|
||||||
tempType,
|
|
||||||
tempVal,
|
|
||||||
host,
|
|
||||||
sysRhel,
|
|
||||||
}
|
|
||||||
|
|
||||||
const _cmdList = [
|
|
||||||
'cat /proc/net/dev && date +%s',
|
'cat /proc/net/dev && date +%s',
|
||||||
'cat /etc/os-release | grep PRETTY_NAME',
|
'cat /etc/os-release | grep PRETTY_NAME',
|
||||||
'cat /proc/stat | grep cpu',
|
'cat /proc/stat | grep cpu',
|
||||||
@@ -35,12 +21,6 @@ const _cmdList = [
|
|||||||
'cat /etc/redhat-release',
|
'cat /etc/redhat-release',
|
||||||
];
|
];
|
||||||
|
|
||||||
final shellFuncStatus = AppShellFunc(
|
|
||||||
'status',
|
|
||||||
_cmdList.join('\necho $seperator\n'),
|
|
||||||
's',
|
|
||||||
);
|
|
||||||
|
|
||||||
const dockerCmds = [
|
const dockerCmds = [
|
||||||
'docker version',
|
'docker version',
|
||||||
'docker ps -a',
|
'docker ps -a',
|
||||||
@@ -48,26 +28,13 @@ const dockerCmds = [
|
|||||||
'docker image ls',
|
'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 = """
|
final shellCmd = """
|
||||||
# Script for app `${BuildData.name} v1.0.${BuildData.build}`
|
# Script for app `${BuildData.name} v1.0.${BuildData.build}`
|
||||||
# Delete this file while app is running will cause app crash
|
# Delete this file while app is running will cause app crash
|
||||||
|
|
||||||
export LANG=en_US.utf-8
|
export LANG=en_US.utf-8
|
||||||
|
|
||||||
$_generated
|
${AppShellFuncType.shellScript}
|
||||||
""";
|
""";
|
||||||
|
|
||||||
final installShellCmd = "mkdir -p $serverBoxDir && "
|
final installShellCmd = "mkdir -p $serverBoxDir && "
|
||||||
|
|||||||
@@ -456,6 +456,8 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
|||||||
subtitle: Text(_buildSubtitle(_docker.items!), style: grey),
|
subtitle: Text(_buildSubtitle(_docker.items!), style: grey),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
// Bottom padding
|
||||||
|
items.add(height13);
|
||||||
return Column(
|
return Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: items,
|
children: items,
|
||||||
|
|||||||
Reference in New Issue
Block a user