Compare commits

..

No commits in common. "main" and "0.1" have entirely different histories.
main ... 0.1

13 changed files with 84 additions and 340 deletions

BIN
.ex.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

BIN
.ex.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 KiB

5
.gitignore vendored
View File

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

View File

@ -1,42 +1,17 @@
# Void Service Control (VSC)
## 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:
**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
$ pip install void-service-control
```
---
**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
```
or by downloading the pre-built binary from the **[releases](https://git.orudo.ru/trueold89/void-service-control/releases)** page
***
@ -54,45 +29,15 @@ $ vsc e <service_name>
$ vsc d <service_name>
```
**Action with multiple services:**
```bash
$ vsc e <first_service_name> <second_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.jpg)
![](.ex.png)

View File

@ -1,176 +0,0 @@
# -*- 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

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

View File

@ -1,22 +0,0 @@
# -*- 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()

View File

@ -1,21 +0,0 @@
#!/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

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

View File

@ -1,12 +0,0 @@
# 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=

View File

@ -1,18 +0,0 @@
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 Executable file
View File

@ -0,0 +1,81 @@
#!/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()