mirror of
https://github.com/lollipopkit/flutter_server_box.git
synced 2025-12-17 07:14:28 +01:00
fix #168
This commit is contained in:
@@ -10,9 +10,9 @@ const _serverBoxDir = r'$HOME/.config/server_box';
|
||||
/// Issue #159
|
||||
/// Use script commit count as version of shell script.
|
||||
/// So different version of app can run at the same time.
|
||||
const _shellPath = '$_serverBoxDir/mobile_v${BuildData.script}.sh';
|
||||
const installShellPath = '$_serverBoxDir/mobile_v${BuildData.script}.sh';
|
||||
|
||||
enum AppShellFuncType {
|
||||
enum ShellFunc {
|
||||
status,
|
||||
docker,
|
||||
process,
|
||||
@@ -22,48 +22,48 @@ enum AppShellFuncType {
|
||||
|
||||
String get flag {
|
||||
switch (this) {
|
||||
case AppShellFuncType.status:
|
||||
case ShellFunc.status:
|
||||
return 's';
|
||||
case AppShellFuncType.docker:
|
||||
case ShellFunc.docker:
|
||||
return 'd';
|
||||
case AppShellFuncType.process:
|
||||
case ShellFunc.process:
|
||||
return 'p';
|
||||
case AppShellFuncType.shutdown:
|
||||
case ShellFunc.shutdown:
|
||||
return 'sd';
|
||||
case AppShellFuncType.reboot:
|
||||
case ShellFunc.reboot:
|
||||
return 'r';
|
||||
}
|
||||
}
|
||||
|
||||
String get exec => 'sh $_shellPath -$flag';
|
||||
String get exec => 'sh $installShellPath -$flag';
|
||||
|
||||
String get name {
|
||||
switch (this) {
|
||||
case AppShellFuncType.status:
|
||||
case ShellFunc.status:
|
||||
return 'status';
|
||||
case AppShellFuncType.docker:
|
||||
case ShellFunc.docker:
|
||||
// `dockeR` -> avoid conflict with `docker` command
|
||||
// 以防止循环递归
|
||||
return 'dockeR';
|
||||
case AppShellFuncType.process:
|
||||
case ShellFunc.process:
|
||||
return 'process';
|
||||
case AppShellFuncType.shutdown:
|
||||
case ShellFunc.shutdown:
|
||||
return 'ShutDown';
|
||||
case AppShellFuncType.reboot:
|
||||
case ShellFunc.reboot:
|
||||
return 'Reboot';
|
||||
}
|
||||
}
|
||||
|
||||
String get cmd {
|
||||
switch (this) {
|
||||
case AppShellFuncType.status:
|
||||
case ShellFunc.status:
|
||||
return '''
|
||||
if [ "\$macSign" = "" ] && [ "\$bsdSign" = "" ]; then
|
||||
\t${_statusCmds.join(_cmdDivider)}
|
||||
else
|
||||
\t${_bsdStatusCmd.join(_cmdDivider)}
|
||||
fi''';
|
||||
case AppShellFuncType.docker:
|
||||
case ShellFunc.docker:
|
||||
return '''
|
||||
result=\$(docker version 2>&1 | grep "permission denied")
|
||||
if [ "\$result" != "" ]; then
|
||||
@@ -71,7 +71,7 @@ if [ "\$result" != "" ]; then
|
||||
else
|
||||
\t${_dockerCmds.map((e) => "sudo -S $e").join(_cmdDivider)}
|
||||
fi''';
|
||||
case AppShellFuncType.process:
|
||||
case ShellFunc.process:
|
||||
return '''
|
||||
if [ "\$macSign" = "" ] && [ "\$bsdSign" = "" ]; then
|
||||
\tif [ "\$isBusybox" != "" ]; then
|
||||
@@ -83,14 +83,14 @@ else
|
||||
\tps -ax
|
||||
fi
|
||||
''';
|
||||
case AppShellFuncType.shutdown:
|
||||
case ShellFunc.shutdown:
|
||||
return '''
|
||||
if [ "\$userId" = "0" ]; then
|
||||
\tshutdown -h now
|
||||
else
|
||||
\tsudo -S shutdown -h now
|
||||
fi''';
|
||||
case AppShellFuncType.reboot:
|
||||
case ShellFunc.reboot:
|
||||
return '''
|
||||
if [ "\$userId" = "0" ]; then
|
||||
\treboot
|
||||
@@ -100,8 +100,25 @@ fi''';
|
||||
}
|
||||
}
|
||||
|
||||
static final String shellScript = () {
|
||||
static final String allScript = () {
|
||||
final sb = StringBuffer();
|
||||
sb.write('''
|
||||
#!/bin/sh
|
||||
# Script for ServerBox app v1.0.${BuildData.build}
|
||||
# DO NOT delete this file while app is running
|
||||
|
||||
export LANG=en_US.UTF-8
|
||||
|
||||
# If macSign & bsdSign are both empty, then it's linux
|
||||
macSign=\$(uname 2>&1 | grep "Darwin")
|
||||
bsdSign=\$(uname 2>&1 | grep "BSD")
|
||||
|
||||
# Link /bin/sh to busybox?
|
||||
isBusybox=\$(ls -l /bin/sh | grep "busybox")
|
||||
|
||||
userId=\$(id -u)
|
||||
|
||||
''');
|
||||
// Write each func
|
||||
for (final func in values) {
|
||||
sb.write('''
|
||||
@@ -212,31 +229,12 @@ const _bsdStatusCmd = [
|
||||
'hostname',
|
||||
];
|
||||
|
||||
final _shellCmd = """
|
||||
#!/bin/sh
|
||||
# Script for ServerBox app v1.0.${BuildData.build}
|
||||
# DO NOT delete this file while app is running
|
||||
|
||||
export LANG=en_US.UTF-8
|
||||
|
||||
# If macSign & bsdSign are both empty, then it's linux
|
||||
macSign=\$(uname 2>&1 | grep "Darwin")
|
||||
bsdSign=\$(uname 2>&1 | grep "BSD")
|
||||
|
||||
# Link /bin/sh to busybox?
|
||||
isBusybox=\$(ls -l /bin/sh | grep "busybox")
|
||||
|
||||
userId=\$(id -u)
|
||||
|
||||
${AppShellFuncType.shellScript}
|
||||
""";
|
||||
|
||||
/// Issue #168
|
||||
/// Use `sh` for compatibility
|
||||
final installShellCmd = """
|
||||
mkdir -p $_serverBoxDir
|
||||
sh -c cat << 'EOF' > $_shellPath
|
||||
$_shellCmd
|
||||
cat << 'EOF' > $installShellPath
|
||||
${ShellFunc.allScript}
|
||||
EOF
|
||||
chmod +x $_shellPath
|
||||
chmod +x $installShellPath
|
||||
""";
|
||||
|
||||
@@ -70,7 +70,7 @@ class ServerPrivateInfo {
|
||||
return data;
|
||||
}
|
||||
|
||||
Server? get findServer => Providers.server.servers[id];
|
||||
Server? get server => Providers.server.pick(spi: this);
|
||||
|
||||
bool shouldReconnect(ServerPrivateInfo old) {
|
||||
return id != old.id ||
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:toolbox/core/utils/platform/path.dart';
|
||||
import 'package:toolbox/data/model/app/shell_func.dart';
|
||||
import 'package:toolbox/data/model/server/system.dart';
|
||||
import 'package:toolbox/data/model/sftp/req.dart';
|
||||
import 'package:toolbox/data/res/logger.dart';
|
||||
import 'package:toolbox/data/res/path.dart';
|
||||
import 'package:toolbox/data/res/provider.dart';
|
||||
import 'package:toolbox/data/res/store.dart';
|
||||
|
||||
import '../../core/extension/order.dart';
|
||||
@@ -20,7 +25,7 @@ typedef ServersMap = Map<String, Server>;
|
||||
|
||||
class ServerProvider extends ChangeNotifier {
|
||||
final ServersMap _servers = {};
|
||||
ServersMap get servers => _servers;
|
||||
Iterable<Server> get servers => _servers.values;
|
||||
final Order<String> _serverOrder = [];
|
||||
Order<String> get serverOrder => _serverOrder;
|
||||
final List<String> _tags = [];
|
||||
@@ -58,6 +63,19 @@ class ServerProvider extends ChangeNotifier {
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
/// Get a [Server] by [spi] or [id].
|
||||
///
|
||||
/// Priority: [spi] > [id]
|
||||
Server? pick({ServerPrivateInfo? spi, String? id}) {
|
||||
if (spi != null) {
|
||||
return _servers[spi.id];
|
||||
}
|
||||
if (id != null) {
|
||||
return _servers[id];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
void _updateTags() {
|
||||
_tags.clear();
|
||||
for (final s in _servers.values) {
|
||||
@@ -264,12 +282,27 @@ class ServerProvider extends ChangeNotifier {
|
||||
try {
|
||||
final writeResult = await s.client?.run(installShellCmd).string;
|
||||
if (writeResult == null || writeResult.isNotEmpty) {
|
||||
_limiter.inc(sid);
|
||||
s.status.failedInfo = writeResult;
|
||||
_setServerState(s, ServerState.failed);
|
||||
return;
|
||||
throw Exception('$writeResult');
|
||||
}
|
||||
} catch (e) {
|
||||
var sftpFailed = false;
|
||||
try {
|
||||
Loggers.app.warning('Using SFTP to write script to ${spi.name}');
|
||||
final localPath = joinPath(await Paths.doc, 'install.sh');
|
||||
final file = File(localPath);
|
||||
file.writeAsString(ShellFunc.allScript);
|
||||
final sftp = Providers.sftp;
|
||||
final completer = Completer();
|
||||
sftp.add(
|
||||
SftpReq(spi, installShellPath, localPath, SftpReqType.upload),
|
||||
completer: completer,
|
||||
);
|
||||
await completer.future;
|
||||
await file.delete();
|
||||
} catch (_) {
|
||||
sftpFailed = true;
|
||||
}
|
||||
if (sftpFailed) {
|
||||
_limiter.inc(sid);
|
||||
s.status.failedInfo = e.toString();
|
||||
_setServerState(s, ServerState.failed);
|
||||
@@ -277,14 +310,15 @@ class ServerProvider extends ChangeNotifier {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (s.client == null) return;
|
||||
|
||||
/// Keep [finished] state, or the UI will be refreshed to [loading] state
|
||||
/// instead of the 'Temp & Uptime'.
|
||||
if (s.state != ServerState.finished) {
|
||||
_setServerState(s, ServerState.loading);
|
||||
}
|
||||
|
||||
final raw = await s.client?.run(AppShellFuncType.status.exec).string;
|
||||
final raw = await s.client?.run(ShellFunc.status.exec).string;
|
||||
final segments = raw?.split(seperator).map((e) => e.trim()).toList();
|
||||
if (raw == null || raw.isEmpty || segments == null || segments.isEmpty) {
|
||||
_limiter.inc(sid);
|
||||
|
||||
Reference in New Issue
Block a user