Compare commits
No commits in common. "main" and "0.1" have entirely different histories.
|
@ -1,5 +0,0 @@
|
||||||
old/
|
|
||||||
__pycache__
|
|
||||||
.idea
|
|
||||||
.venv
|
|
||||||
probe.py
|
|
61
README.md
61
README.md
|
@ -1,42 +1,17 @@
|
||||||
# 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 / xbps-package from the **[releases](https://git.orudo.ru/trueold89/void-service-control/releases)** page**
|
or by downloading the pre-built binary 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
|
|
||||||
```
|
|
||||||
|
|
||||||
***
|
***
|
||||||
|
|
||||||
|
@ -54,45 +29,15 @@ $ vsc e <service_name>
|
||||||
$ vsc d <service_name>
|
$ vsc d <service_name>
|
||||||
```
|
```
|
||||||
|
|
||||||
**Action with multiple services:**
|
**Print help**
|
||||||
```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)
|
|
||||||
|
|
||||||
|
|
|
@ -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)
|
|
|
@ -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"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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()
|
|
|
@ -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()
|
|
|
@ -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} <название_сервиса> - Выключить и удалить из автозапуска"
|
|
||||||
}
|
|
||||||
}
|
|
12
VoidTemplate
12
VoidTemplate
|
@ -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=
|
|
18
setup.py
18
setup.py
|
@ -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'],
|
|
||||||
},
|
|
||||||
)
|
|
|
@ -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()
|
Loading…
Reference in New Issue