Compare commits

...

14 Commits
0.1 ... main

Author SHA1 Message Date
trueold89 63a941b52b
Json files are h-readable now 2024-03-28 01:02:07 +03:00
trueold89 635e0b55f8
0.2.1
- Now you can manage multiple services
- Reviewed-on: #2
2024-03-28 00:11:47 +03:00
trueold89 f245de2044
Add xbps-src template 2024-03-28 00:07:28 +03:00
trueold89 3f15909e69
Update README.md && setup.py 2024-03-28 00:07:21 +03:00
trueold89 ae747ca569
You can now manage multiple services && main.py is now indexed in the repository 2024-03-27 23:45:34 +03:00
trueold89 2280b74221
0.2
- Rewrited
- Add multi-lang support
---
Current languages:
- English
- Russian
2024-03-25 07:52:08 +03:00
trueold89 326c163e61
Update README.md 2024-03-25 07:42:56 +03:00
trueold89 ddc5e0c72f
0 argument bugfix 2024-03-25 07:17:17 +03:00
trueold89 41422cce40
Create package 2024-03-25 07:14:53 +03:00
trueold89 10447aa6bd
Add russian language 2024-03-25 06:45:26 +03:00
trueold89 321f506fcb
Add multi-lang support 2024-03-25 06:45:03 +03:00
trueold89 776d025e72
Add docstrings 2024-03-25 05:37:45 +03:00
trueold89 73617c67dd
Rewrite to OOP 2024-03-25 05:20:41 +03:00
trueold89 b59d35c146
Init yet another rewrite 2024-03-25 02:51:48 +03:00
13 changed files with 340 additions and 84 deletions

BIN
.ex.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

BIN
.ex.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 202 KiB

5
.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
old/
__pycache__
.idea
.venv
probe.py

View File

@ -1,17 +1,42 @@
# Void Service Control (VSC) # Void Service Control (VSC)
## A simple script that will allow you to manage runit services in Void Linux ## A simple script that will allow you to manage runit services in Void Linux
## Available on:
[![](https://cloud.orudo.ru/apps/files_sharing/publicpreview/RpcoJB8FwgNmqHC?file=/&fileId=48757&x=1920&y=1200&a=true&etag=10effec96382ba8b9fc181a5c1c85012)](https://git.orudo.ru/trueold89/void-service-control)
[![](https://cloud.orudo.ru/s/D8xtkTS8ZBCq8fC/download/GH.png)](https://github.com/Trueold89/void-service-control)
***
- [Installation](#install)
- [Usage](#usage)
- [Build from sources](#build-from_sources)
- [Example (Screenshot)](#example)
### Install: ### Install:
**You can install vsc using pip:** **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.1/VoidServiceControl-0.2.1.tar.gz
```
or pypi
```bash ```bash
$ pip install void-service-control $ 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**
#### Install [.xbps package](https://git.orudo.ru/trueold89/void-service-control/releases):
```bash
& xbps-rindex -a *.xbps && xbps-install --repository=$PWD void-service-control
```
*** ***
@ -29,15 +54,45 @@ $ vsc e <service_name>
$ vsc d <service_name> $ vsc d <service_name>
``` ```
**Print help** **Action with multiple services:**
```bash
$ vsc e <first_service_name> <second_service_name>
```
**Print help:**
```bash ```bash
$ vsc --help $ vsc --help
``` ```
*All commands require root privileges* *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: ## Example:
![](.ex.png)
![](.ex.jpg)

View File

View File

@ -0,0 +1,176 @@
# -*- 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) == 1 and self.__arguments[0] in Arg.HELP.value:
raise Help()
if len(self.__arguments) < 2:
raise TypeError(lang.errors["usage"])
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)

View File

@ -0,0 +1,14 @@
{
"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"
}
}

22
VoidServiceControl/env.py Normal file
View File

@ -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()

21
VoidServiceControl/main.py Executable file
View File

@ -0,0 +1,21 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
from VoidServiceControl.classes import Su, Interface, Args, Help
def main() -> None:
try:
Su()
action, services = tuple(Args())
for service_name in services:
service = Interface(service_name)
service.action(action)
del service
except TypeError as e:
print(f"{e}\n\n{Help()}")
except (ValueError, PermissionError, Help) as e:
print(e)
if __name__ == '__main__':
main()

View File

@ -0,0 +1,14 @@
{
"errors": {
"su": "Ошибка: Доступ запрещен",
"usage": "Ошибка: Неверное использование",
"args": "Ошибка: Неверные аргументы",
"ne": "Ошибка: Сервис '{}' не существует",
"enabled": "Ошибка: Сервис '{}' уже включен",
"disabled": "Ошибка: Сервис '{}' уже выключен"},
"messages": {
"enabled": "Сервис '{}' успешно включен",
"disabled": "Сервис '{}' успешно выключен",
"help": "Использование:\n---\nvsc {e/enable/on/up} <название_сервиса> - Запустить и добавить в автозапуск\nvsc {d/disable/off/down} <название_сервиса> - Выключить и удалить из автозапуска"
}
}

12
VoidTemplate Normal file
View File

@ -0,0 +1,12 @@
# Template file for 'void-service-control'
pkgname=void-service-control
version=
revision=1
build_style=python3-module
hostmakedepends="python3-setuptools"
short_desc="A simple script that will allow you to manage runit services in Void Linux"
maintainer="Trueold89 <trueold89@orudo.ru>"
license="GPL-3"
homepage="https://git.orudo.ru/trueold89/void-service-control"
distfiles="https://git.orudo.ru/trueold89/void-service-control/releases/download/${version}/VoidServiceControl-${version}.tar.gz"
checksum=

18
setup.py Normal file
View File

@ -0,0 +1,18 @@
from setuptools import setup
setup(
name='VoidServiceControl',
version='0.2.1',
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
View File

@ -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()