Indocator rslsync

Indocator rslsync
« kdy: 01. 06. 2022, 12:26:47 »
Je možné v gnome shell 42 nějak indikovat spuštěný program rslsync který otevírá na localhost port 8888?

Po spuštění se na localhost otevře port 8888 kde přes webový prohlížeč jde pozorovat a konfigurovat. Občas se stane že to spadne, a já bych to potřeboval nějak vědět bez toho abych to musel mít stále otevřené v prohlížeči.

Při spuštěném rslsync:
Kód: [Vybrat]
$ nmap -p 8888 127.0.0.1
Starting Nmap 7.80 ( https://nmap.org ) at 2022-06-01 12:12 CEST
Nmap scan report for localhost (127.0.0.1)
Host is up (0.00013s latency).

PORT     STATE SERVICE
8888/tcp open  sun-answerbook

Nmap done: 1 IP address (1 host up) scanned in 0.07 seconds

Při vypnutém:
Kód: [Vybrat]
$ nmap -p 8888 127.0.0.1
Starting Nmap 7.80 ( https://nmap.org ) at 2022-06-01 12:13 CEST
Nmap scan report for localhost (127.0.0.1)
Host is up (0.00012s latency).

PORT     STATE  SERVICE
8888/tcp closed sun-answerbook

Nmap done: 1 IP address (1 host up) scanned in 0.06 seconds

Napadlo mě zda nepoužít nějaký extensions
https://extensions.gnome.org/extension/4687/server-status-indicator/
https://extensions.gnome.org/extension/4989/home-server/
Jenže tak snadné to není. Ale bylo by fajn mít nahoře ikonku která "zčervená" pokud http://127.0.0.1:8888/ není dostupná.

Nějaké nápady?


Re:Indocator rslsync
« Odpověď #1 kdy: 01. 06. 2022, 16:04:21 »
Spustil bych v tmuxu/screenu cyklus
Kód: [Vybrat]
while [ 1 ]; do
nc -zv 127.0.0.1 8888 2>/dev/null
if [ "$?" -ne "0" ]; then
    zenity --info --text="$(date) nedostupny port";
fi
sleep 30s
done
pripadne doplnit o zaslani emailu

ja.

  • ***
  • 232
    • Zobrazit profil
    • E-mail
Re:Indocator rslsync
« Odpověď #2 kdy: 01. 06. 2022, 16:24:12 »
Co tak urobit z toho systemd user service a potom v ramci definicie unitu bud sluzbu restartovat (Restart=on-failure?), alebo urobit nejaku akciu pri chybe (OnFailure=...?).

Jose D

  • *****
  • 762
    • Zobrazit profil
Re:Indocator rslsync
« Odpověď #3 kdy: 01. 06. 2022, 16:30:07 »
systemd user service
ano, myslím si, že tohle je řešení, které pokryje i logování.

Re:Indocator rslsync
« Odpověď #4 kdy: 12. 06. 2022, 14:05:37 »
Já bych spíš opravdu "vizuální" kontrolu.
Nšel by tento extension upravit aby kontoloval ne jen IP ale i port?
https://extensions.gnome.org/extension/4989/home-server/
Kód: [Vybrat]
const { GObject, St, Clutter, GLib, Gio } = imports.gi;

const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension();
const ByteArray = imports.byteArray;
const Util = imports.misc.util;
const Main = imports.ui.main;
const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu;

const Gettext = imports.gettext;
const Domain = Gettext.domain(Me.metadata.uuid);
const _ = Domain.gettext;

const Status = {
    ONLINE: 1,
    OFFLINE: 2,
    ERROR: 3,
    UNDEFINED: 4,
};

const Icon = {
    ONLINE: 'online.svg',
    OFFLINE: 'offline.svg',
    ERROR: 'error.svg',
    UNDEFINED: 'undefined.svg',
};

const Settings = {
    SERVER_MAC: 'servermac',
    SERVER_IP: 'serverip',
    SERVER_POLL: 'serverpoll',
};

const HomeServer = GObject.registerClass(
    class HomeServerIndicator extends PanelMenu.Button {
        _init() {
            super._init(0.0, _('Server'));
            this._indicatorStatus = {
                lastResponse: null,
                status: Status.UNDEFINED,
            };
            this._settings = ExtensionUtils.getSettings();
            this._isConnected = false;
            this._setupWidgets();

            this._mainLoop();
            this._startMainLoop();
        }

        _setupWidgets() {
            this._menuLayout = new St.BoxLayout();
            this._ServerIcon = new St.Icon({ style_class: 'system-status-icon' });
            this._setIndicatorIcon(Icon.UNDEFINED);
            this._menuLayout.add_actor(this._ServerIcon);
            this.add_actor(this._menuLayout);
            this._setupPopupMenu();
        }

        _setupPopupMenu() {
            this._settingsMenuItem = new PopupMenu.PopupMenuItem(_('Settings'));
            this._settingsMenuItem.connect('activate', () => {
                const extensionManager = imports.ui.main.extensionManager;
                extensionManager.openExtensionPrefs(Me.uuid, '', {});
            });
            this.menu.addMenuItem(this._settingsMenuItem);
        }

        _setIndicatorIcon(iconFileName) {
            const iconPath = Me.dir
                .get_child('icons')
                .get_child(iconFileName)
                .get_path();
            this._ServerIcon.set_gicon(Gio.Icon.new_for_string(iconPath));
        }

        _setIndicator(status) {
            if (status == Status.ONLINE) {
                if ( this._indicatorStatus.status !== Status.ONLINE ) {
                    this._setIndicatorIcon(Icon.ONLINE);
                    this._log('Set status ONLINE');
                    this._indicatorStatus.status = Status.ONLINE;
                    if (this._wakeonlanMenuItem) {
                        this._log('Remove WOL menu item');
                        this._wakeonlanMenuItem.disconnect();
                        this._wakeonlanMenuItem.destroy();
                    }   
                }
                return;
            }
           
            if (status == Status.OFFLINE) {
                if ( this._indicatorStatus.status !== Status.OFFLINE ) {
                    this._setIndicatorIcon(Icon.OFFLINE);
                    this._log('Set status OFFLINE');
                    this._indicatorStatus.status = Status.OFFLINE;
                    if (!this._wakeonlanMenuItem) {
                        this._log('Add WOL menu item');
                        this._wakeonlanMenuItem = new PopupMenu.PopupMenuItem(_('Start Server'));
                        this._wakeonlanMenuItem.connect('activate', () => {
                            this._wakeup();
                        });
                        this.menu.addMenuItem(this._wakeonlanMenuItem);
                    }
                }
                return;
            }

            if (status == Status.ERROR) {
                if ( this._indicatorStatus.status !== Status.ERROR ) {
                    this._setIndicatorIcon(Icon.ERROR);
                    this._log('Set status ERROR');
                    this._indicatorStatus.status = Status.ERROR;
                    if (this._wakeonlanMenuItem) {
                        this._log('Remove WOL menu item');
                        this._wakeonlanMenuItem.disconnect();
                        this._wakeonlanMenuItem.destroy();
                    }   
                }
                return;
            }

            if (status == Status.UNDEFINED) {
                if ( this._indicatorStatus.status !== Status.UNDEFINED ) {
                    this._setIndicatorIcon(Icon.UNDEFINED);
                    this._log('Set status UNDEFINED');
                    this._indicatorStatus.status = Status.UNDEFINED;
                    if (this._wakeonlanMenuItem) {
                        this._log('Remove WOL menu item');
                        this._wakeonlanMenuItem.disconnect();
                        this._wakeonlanMenuItem.destroy();
                    }   
                }
                return;
            }
        }

        _wakeup() {
            try {
                let proc = Gio.Subprocess.new(
                    ['wakeonlan', this._settings.get_string('servermac')],
                    Gio.SubprocessFlags.STDOUT_PIPE | Gio.SubprocessFlags.STDERR_PIPE);
                proc.communicate_utf8_async(null, null, (proc, res) => {
                    try {
                        Main.notify(Me.metadata.name, _('Start Server now. Please wait...'))
                        let [, stdout, stderr] = proc.communicate_utf8_finish(res);
                    } catch (e) {
                        Main.notify(Me.metadata.name, _('Start Server failed'))
                        this._log('Executing Wake On LAN failed. ' + e);
                    }
                });
            } catch (e) {
                Main.notify(Me.metadata.name, _('Start Server failed. Already installed wakeonlan?'))
                this._log('Wake On LAN failed. Already installed wakeonlan? ' + e);
            }
        }

        _startMainLoop() {
            this._mainLoopTimeout = GLib.timeout_add_seconds(
                GLib.PRIORITY_DEFAULT,
                this._settings.get_int(Settings.SERVER_POLL),
                () => {
                    this._mainLoop();
                    return true;
                }
            );
        }

        _stopMainLoop() {
            if (this._mainLoopTimeout) {
                GLib.source_remove(this._mainLoopTimeout);
                this._mainLoopTimeout = null;
            }
            this._connection = null;
        }

        async _mainLoop() {
            let ip =  this._settings.get_string('serverip')
            let cmd = [];
            if ( this._isConnected == true ) {
                this._log('Connection established');
                cmd = ['sh', '-c', `ping -q -c1 -w5 ${ip} >/dev/null 2>&1`];
            } else {
                this._log('Awaiting established connection');
                cmd = ['sh', '-c', 'ping -q -c1 -w1 `ip r | grep default | cut -d " " -f 3` >/dev/null 2>&1 && exit 0 || exit 1'];
            }
           
            try {
                let proc = Gio.Subprocess.new(cmd, Gio.SubprocessFlags.STDOUT_PIPE | Gio.SubprocessFlags.STDERR_PIPE);
                proc.communicate_utf8_async(null, null, (proc, res) => {
                    try {
                        if (proc.get_successful()) {
                            if ( this._isConnected == true ) {
                                this._log('Ping success');
                                this._setIndicator(Status.ONLINE);
                            } else {
                                this._isConnected = true;
                                this._setIndicator(Status.UNDEFINED);
                            }
                        } else {
                            if ( this._isConnected == true ) {
                                this._log('Ping failed');
                                this._setIndicator(Status.OFFLINE);
                            } else {
                                this._setIndicator(Status.UNDEFINED);
                            }
                        }
                    } catch (e) {
                        this._setIndicator(Status.UNDEFINED);
                        if ( this._isConnected == true ) {
                            this._log('Ping failed. ' + e);
                        } else {
                            this._log('Awaiting connection failed. ' + e);
                        }
                    }
                });
            } catch (e) {
                this._setIndicator(Status.ERROR);
                if ( this._isConnected == true ) {
                    this._log('Ping failed. ' + e);
                } else {
                    this._log('Awaiting connection failed. ' + e);
                }
            }
        }

        _log(msg) {
            if (this._settings.get_boolean('serverdebug')) {
                log(`${Me.metadata.name}: ${msg}`);
            }
        }

        _onDestroy() {
            this._log('Indicator._onDestroy()');
            this._stopMainLoop();
            this._menuLayout = null;
            this._indicatorStatus = null;
            this._settings = null;
            super._onDestroy();
        }
    }
);

class Extension {
    constructor(uuid) {
        this._uuid = uuid;
    }
   
    enable() {
        this._homeServerIndicator = new HomeServer();
        Main.panel.addToStatusArea(this._uuid, this._homeServerIndicator);
    }
   
    disable() {
        this._homeServerIndicator.destroy();
        this._homeServerIndicator = null;
    }
}


function init(meta) {
    ExtensionUtils.initTranslations(Me.metadata.uuid);
    return new Extension(meta.uuid);
}