0.2
- Rewrited - Add multi-lang support --- Current languages: - English - Russian
This commit is contained in:
commit
2280b74221
|
@ -0,0 +1,6 @@
|
|||
old/
|
||||
VoidServiceControl/main.py
|
||||
__pycache__
|
||||
.idea
|
||||
.venv
|
||||
probe.py
|
44
README.md
44
README.md
|
@ -1,17 +1,30 @@
|
|||
# Void Service Control (VSC)
|
||||
## A simple script that will allow you to manage runit services in Void Linux
|
||||
|
||||
- [Installation](#install)
|
||||
- [Usage](#usage)
|
||||
- [Build from sources](#build-from_sources)
|
||||
- [Example (Screenshot)](#example)
|
||||
|
||||
|
||||
### Install:
|
||||
|
||||
**You can install vsc using pip:**
|
||||
|
||||
From [git.orudo.ru](https://git.orudo.ru/trueold89/void-service-control/releases):
|
||||
|
||||
```bash
|
||||
$ pip install https://git.orudo.ru/trueold89/void-service-control/releases/download/0.2/VoidServiceControl-0.2.tar.gz
|
||||
```
|
||||
or pypi
|
||||
|
||||
```bash
|
||||
$ pip install void-service-control
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
or by downloading the pre-built binary from the **[releases](https://git.orudo.ru/trueold89/void-service-control/releases)** page
|
||||
**Or by downloading the pre-built binary / xbps-package from the **[releases](https://git.orudo.ru/trueold89/void-service-control/releases)** page**
|
||||
|
||||
***
|
||||
|
||||
|
@ -29,15 +42,40 @@ $ vsc e <service_name>
|
|||
$ vsc d <service_name>
|
||||
```
|
||||
|
||||
**Print help**
|
||||
**Print help:**
|
||||
|
||||
```bash
|
||||
$ vsc --help
|
||||
```
|
||||
*All commands require root privileges*
|
||||
|
||||
### Build from sources
|
||||
|
||||
**Clone repo:**
|
||||
```bash
|
||||
$ git clone https://git.orudo.ru/trueold89/void-service-control.git --depth=1 && cd void-service-control
|
||||
```
|
||||
|
||||
**Install deps:**
|
||||
```bash
|
||||
$ pip install setuptools
|
||||
```
|
||||
|
||||
**Build sdist:**
|
||||
```bash
|
||||
$ python3 setup.py sdist
|
||||
```
|
||||
|
||||
**Install:**
|
||||
```bash
|
||||
$ pip install dist/*
|
||||
```
|
||||
|
||||
*Last command require root privileges*
|
||||
***
|
||||
|
||||
## Example:
|
||||
|
||||
![](.ex.png)
|
||||
|
||||
![](.ex.jpg)
|
||||
|
||||
|
|
|
@ -0,0 +1,178 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import importlib.resources
|
||||
import json
|
||||
from enum import Enum
|
||||
from os import listdir as ls
|
||||
from subprocess import run as execute
|
||||
from subprocess import PIPE
|
||||
from sys import argv
|
||||
|
||||
|
||||
from VoidServiceControl.env import *
|
||||
|
||||
|
||||
class Help(Exception):
|
||||
def __str__(self) -> str:
|
||||
"""
|
||||
Returns the program usage help
|
||||
:return: Program usage help
|
||||
"""
|
||||
return lang.messages["help"]
|
||||
|
||||
|
||||
def Su() -> None:
|
||||
"""
|
||||
Checks if the user has administrator rights
|
||||
"""
|
||||
user = execute('whoami', shell=True, text=True, stdout=PIPE).stdout[:-1]
|
||||
if user != 'root':
|
||||
raise PermissionError(lang.errors["su"])
|
||||
|
||||
|
||||
# Types of service actions
|
||||
class Action(Enum):
|
||||
ENABLE = ["enable", "e", "on", "up"]
|
||||
DISABLE = ["disable", "d", "off", "down"]
|
||||
|
||||
|
||||
# Types of run arguments
|
||||
class Arg(Enum):
|
||||
HELP = ["--help", "-h", "help"]
|
||||
|
||||
@classmethod
|
||||
def all(cls) -> list[str]:
|
||||
"""
|
||||
Returns all types of run arguments
|
||||
:return: All types of run arguments list
|
||||
"""
|
||||
return cls.HELP.value + cls.__action()
|
||||
|
||||
@classmethod
|
||||
def __action(cls) -> list[str]:
|
||||
"""
|
||||
Returns all types of service actions
|
||||
:return: All types of service actions list
|
||||
"""
|
||||
actions = list(map(lambda action: action.value, Action))
|
||||
out = []
|
||||
for lst in actions:
|
||||
out.extend(lst)
|
||||
return out
|
||||
|
||||
|
||||
class Args(object):
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.__arguments = argv[1:]
|
||||
self.__check()
|
||||
|
||||
def __check(self) -> None:
|
||||
"""
|
||||
Checks the arguments
|
||||
"""
|
||||
if len(self.__arguments) == 0:
|
||||
raise TypeError(lang.errors["usage"])
|
||||
if len(self.__arguments) != 2 and self.__arguments[0] not in Arg.HELP.value:
|
||||
raise TypeError(lang.errors["usage"])
|
||||
if self.__arguments[0] in Arg.HELP.value:
|
||||
raise Help()
|
||||
if self.__arguments[0] not in Arg.all():
|
||||
raise TypeError(lang.errors["args"])
|
||||
|
||||
def __action(self) -> Action:
|
||||
"""
|
||||
Returns the action to the service
|
||||
:return: Service action
|
||||
"""
|
||||
actions = list(Action)
|
||||
for action in actions:
|
||||
if self.__arguments[0] in action.value:
|
||||
return action
|
||||
|
||||
def __iter__(self):
|
||||
yield self.__action()
|
||||
yield self.__arguments[1]
|
||||
|
||||
|
||||
class Service(object):
|
||||
__enabled = False
|
||||
|
||||
def __init__(self, name: str) -> None:
|
||||
self.__name = name
|
||||
self.__check()
|
||||
|
||||
def __check(self) -> None:
|
||||
"""
|
||||
Checks if the service exists and is enabled
|
||||
"""
|
||||
all_services = ls(SV_PATH)
|
||||
enabled_services = ls(ENABLED_PATH)
|
||||
if self.__name not in all_services:
|
||||
raise ValueError(lang.errors["ne"].format(self.getname()))
|
||||
if self.__name in enabled_services:
|
||||
self.__enabled = True
|
||||
|
||||
def getname(self) -> str:
|
||||
"""
|
||||
Returns the service name
|
||||
:return: Service name
|
||||
"""
|
||||
return self.__name
|
||||
|
||||
def enable(self) -> None:
|
||||
"""
|
||||
Enable the service
|
||||
"""
|
||||
if self.__enabled:
|
||||
raise ValueError(lang.errors["enabled"].format(self.getname()))
|
||||
execute(f'ln -s {SV_PATH}/{self.__name} {ENABLED_PATH}/', shell=True)
|
||||
|
||||
def disable(self):
|
||||
"""
|
||||
Disable the service
|
||||
"""
|
||||
if not self.__enabled:
|
||||
raise ValueError(lang.errors["disabled"].format(self.getname()))
|
||||
execute(f'rm {ENABLED_PATH}/{self.__name}', shell=True)
|
||||
|
||||
|
||||
class Interface(object):
|
||||
|
||||
def __init__(self, service: str) -> None:
|
||||
self.service = Service(service)
|
||||
|
||||
def action(self, action: Action) -> None:
|
||||
"""
|
||||
Performs an action on the service
|
||||
:param action: Action on the service
|
||||
"""
|
||||
match action:
|
||||
case Action.ENABLE:
|
||||
self.service.enable()
|
||||
print(lang.messages["enabled"].format(self.service.getname()))
|
||||
case Action.DISABLE:
|
||||
self.service.disable()
|
||||
print(lang.messages["disabled"].format(self.service.getname()))
|
||||
|
||||
|
||||
class Translate(object):
|
||||
|
||||
def __init__(self, language: str):
|
||||
"""
|
||||
:param language: Language (ex. en_US)
|
||||
"""
|
||||
self.lang = language
|
||||
self.errors = self.__translation["errors"]
|
||||
self.messages = self.__translation["messages"]
|
||||
|
||||
@property
|
||||
def __translation(self):
|
||||
try:
|
||||
with importlib.resources.open_text(__package__, f"{self.lang}.json", "utf-8") as json_file:
|
||||
return json.loads(json_file.read())
|
||||
except FileNotFoundError:
|
||||
with importlib.resources.open_text(__package__, f"en_US.json", "utf-8") as json_file:
|
||||
return json.loads(json_file.read())
|
||||
|
||||
|
||||
lang = Translate(LANG)
|
|
@ -0,0 +1 @@
|
|||
{"errors": {"su": "Error: Access denied", "usage": "Bad usage", "args": "Error: Invalid args", "ne": "Error: Service '{}' doesn't exists", "enabled": "Error: Service '{}' already enabled", "disabled": "Error: Service '{}' already disabled"}, "messages": {"enabled": "Service '{}' successfully enabled", "disabled": "Service '{}' successfully disabled", "help": "Usage:\n---\nvsc {e/enable/on/up} <service_name> - Run service and add it to autostart\nvsc {d/disable/off/down <service_name> - Stop service and remove it from autostart"}}
|
|
@ -0,0 +1,22 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from os import environ
|
||||
|
||||
# Edit these lines if you are using custom paths to Runit services
|
||||
|
||||
SV_PATH = '/etc/sv'
|
||||
ENABLED_PATH = '/var/service'
|
||||
|
||||
|
||||
# Lang settings
|
||||
def lang() -> str:
|
||||
"""
|
||||
Get system lang
|
||||
:return: system lang
|
||||
"""
|
||||
try:
|
||||
return environ["LANG"][:5]
|
||||
except KeyError:
|
||||
return "en_US"
|
||||
|
||||
|
||||
LANG = lang()
|
|
@ -0,0 +1 @@
|
|||
{"errors": {"su": "\u041e\u0448\u0438\u0431\u043a\u0430: \u0414\u043e\u0441\u0442\u0443\u043f \u0437\u0430\u043f\u0440\u0435\u0449\u0435\u043d", "usage": "\u041e\u0448\u0438\u0431\u043a\u0430: \u041d\u0435\u0432\u0435\u0440\u043d\u043e\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435", "args": "\u041e\u0448\u0438\u0431\u043a\u0430: \u041d\u0435\u0432\u0435\u0440\u043d\u044b\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b", "ne": "\u041e\u0448\u0438\u0431\u043a\u0430: \u0421\u0435\u0440\u0432\u0438\u0441 '{}' \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442", "enabled": "\u041e\u0448\u0438\u0431\u043a\u0430: \u0421\u0435\u0440\u0432\u0438\u0441 '{}' \u0443\u0436\u0435 \u0432\u043a\u043b\u044e\u0447\u0435\u043d", "disabled": "\u041e\u0448\u0438\u0431\u043a\u0430: \u0421\u0435\u0440\u0432\u0438\u0441 '{}' \u0443\u0436\u0435 \u0432\u044b\u043a\u043b\u044e\u0447\u0435\u043d"}, "messages": {"enabled": "\u0421\u0435\u0440\u0432\u0438\u0441 '{}' \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0432\u043a\u043b\u044e\u0447\u0435\u043d", "disabled": "\u0421\u0435\u0440\u0432\u0438\u0441 '{}' \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0432\u044b\u043a\u043b\u044e\u0447\u0435\u043d", "help": "\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435:\n---\nvsc {e/enable/on/up} <\u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435_\u0441\u0435\u0440\u0432\u0438\u0441\u0430> - \u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 \u0430\u0432\u0442\u043e\u0437\u0430\u043f\u0443\u0441\u043a\nvsc {d/disable/off/down <\u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435_\u0441\u0435\u0440\u0432\u0438\u0441\u0430> - \u0412\u044b\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0438 \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u0438\u0437 \u0430\u0432\u0442\u043e\u0437\u0430\u043f\u0443\u0441\u043a\u0430"}}
|
|
@ -0,0 +1,18 @@
|
|||
from setuptools import setup
|
||||
|
||||
setup(
|
||||
name='VoidServiceControl',
|
||||
version='0.2',
|
||||
url='https://git.orudo.ru/trueold89/void-service-control',
|
||||
author='trueold89',
|
||||
author_email='trueold89@orudo.ru',
|
||||
description="A simple script that will allow you to manage runit services in Void Linux",
|
||||
packages=['VoidServiceControl'],
|
||||
long_description=open('README.md').read(),
|
||||
entry_points={
|
||||
"console_scripts": ["vsc = VoidServiceControl.main:main"]
|
||||
},
|
||||
package_data={
|
||||
'VoidServiceControl': ['*.json'],
|
||||
},
|
||||
)
|
81
vsc.py
81
vsc.py
|
@ -1,81 +0,0 @@
|
|||
#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Import
|
||||
import os, subprocess, sys
|
||||
|
||||
# Const
|
||||
SV_PATH = '/etc/sv'
|
||||
ENABLED_PATH = '/var/service'
|
||||
|
||||
# Access
|
||||
def su():
|
||||
out = subprocess.run('whoami', shell=True, text=True, stdout=subprocess.PIPE)
|
||||
user = out.stdout[:-1]
|
||||
if user == 'root':
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
# Print help message
|
||||
def helpmsg():
|
||||
print('''
|
||||
Usage:
|
||||
---
|
||||
vsc {e/enable/on/up} <service_name> - Run service and add it to autostart
|
||||
vsc {d/disable/off/down <service_name> - Stop service and remove it from autostart
|
||||
---
|
||||
''')
|
||||
sys.exit(1)
|
||||
|
||||
# Check exec args
|
||||
def args_check():
|
||||
args = sys.orig_argv[2:]
|
||||
if len(args) == 2:
|
||||
return args
|
||||
elif len(args) == 1 and args[0] in ['--h','--help']:
|
||||
helpmsg()
|
||||
else:
|
||||
return False
|
||||
|
||||
# Check availability
|
||||
def availability(service, action):
|
||||
all = os.listdir(SV_PATH)
|
||||
enabled = os.listdir(ENABLED_PATH)
|
||||
all = service in all
|
||||
if all == False:
|
||||
raise Exception(f"Service '{service}' doesn't exist")
|
||||
if service in enabled:
|
||||
if action == 'on':
|
||||
raise Exception(f"Service '{service}' already enabled")
|
||||
elif action == 'off':
|
||||
return True
|
||||
else:
|
||||
if action == 'off':
|
||||
raise Exception(f"Service '{service}' already disabled")
|
||||
elif action == 'on':
|
||||
return True
|
||||
|
||||
# Main
|
||||
def main():
|
||||
try:
|
||||
args = args_check()
|
||||
if args == False:
|
||||
raise Exception('Bad usage. See --help')
|
||||
if su() == False:
|
||||
raise Exception('Access denied')
|
||||
action, service = args
|
||||
if action in ['enable','e','on','up']:
|
||||
if availability(service,'on'):
|
||||
subprocess.run(f'ln -s {SV_PATH}/{service} {ENABLED_PATH}/', shell=True)
|
||||
print(f"Service '{service}' successfully enabled")
|
||||
if action in ['disable','d','off','down']:
|
||||
if availability(service,'off'):
|
||||
subprocess.run(f'rm {ENABLED_PATH}/{service}', shell=True)
|
||||
print(f"Service '{service}' successfully disabled")
|
||||
except Exception as ex:
|
||||
print(ex)
|
||||
sys.exit(0)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
Loading…
Reference in New Issue