the base
This commit is contained in:
177
lib/osal/screen/factory.v
Normal file
177
lib/osal/screen/factory.v
Normal file
@@ -0,0 +1,177 @@
|
||||
module screen
|
||||
|
||||
// import freeflowuniverse.herolib.osal
|
||||
import freeflowuniverse.herolib.core.texttools
|
||||
// import freeflowuniverse.herolib.screen
|
||||
import os
|
||||
import time
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
|
||||
@[heap]
|
||||
pub struct ScreensFactory {
|
||||
pub mut:
|
||||
screens []Screen
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct ScreensNewArgs {
|
||||
pub:
|
||||
reset bool
|
||||
}
|
||||
|
||||
// return screen instance
|
||||
pub fn new(args ScreensNewArgs) !ScreensFactory {
|
||||
mut t := ScreensFactory{}
|
||||
t.scan()!
|
||||
if args.reset {
|
||||
t.reset()!
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
pub fn init_screen_object(item_ map[string]string) Screen {
|
||||
mut item := Screen{}
|
||||
state_item := item_['state'] or { panic('bug') }
|
||||
item.state = match state_item.trim('() ').to_lower() {
|
||||
'detached' { .detached }
|
||||
else { .unknown }
|
||||
}
|
||||
pre := item_['pre'] or { panic('bug') }
|
||||
item.pid = pre.all_before('.').trim_space().int()
|
||||
item.name = pre.all_after('.').trim_space()
|
||||
return item
|
||||
}
|
||||
|
||||
// loads screen screen, populate the object
|
||||
pub fn (mut self ScreensFactory) scan() ! {
|
||||
self.screens = []Screen{}
|
||||
os.execute('screen -wipe > /dev/null 2>&1') // make sure its all clean
|
||||
res := os.execute('screen -ls')
|
||||
if res.exit_code > 1 {
|
||||
return error('could not find screen or other error, make sure screen is installed.\n${res.output}')
|
||||
}
|
||||
if res.output.contains('No Sockets found') {
|
||||
return
|
||||
}
|
||||
// there is stuff to parses
|
||||
|
||||
res1 := texttools.remove_empty_lines(res.output)
|
||||
.split_into_lines()
|
||||
.filter(it.starts_with(' ') || it.starts_with('\t'))
|
||||
.join_lines()
|
||||
mut res2 := texttools.to_list_map('pre,state', res1, '').map(init_screen_object(it))
|
||||
for mut item in res2 {
|
||||
if self.exists(item.name) {
|
||||
return error('duplicate screen with name: ${item.name}')
|
||||
}
|
||||
self.screens << item
|
||||
}
|
||||
// console.print_debug(self.str())
|
||||
}
|
||||
|
||||
pub struct ScreenAddArgs {
|
||||
pub mut:
|
||||
name string @[requred]
|
||||
cmd string
|
||||
reset bool
|
||||
start bool = true
|
||||
attach bool
|
||||
}
|
||||
|
||||
// print list of screen screens
|
||||
pub fn (mut self ScreensFactory) add(args_ ScreenAddArgs) !Screen {
|
||||
mut args := args_
|
||||
if args.cmd == '' {
|
||||
args.cmd = '/bin/bash'
|
||||
}
|
||||
if args.name.len < 3 {
|
||||
return error('name needs to be at least 3 chars.')
|
||||
}
|
||||
if self.exists(args.name) {
|
||||
if args.reset {
|
||||
self.kill(args.name)!
|
||||
} else {
|
||||
return self.get(args.name)!
|
||||
}
|
||||
}
|
||||
self.screens << Screen{
|
||||
name: args.name
|
||||
cmd: args.cmd
|
||||
}
|
||||
if args.start {
|
||||
self.start(args.name)!
|
||||
}
|
||||
mut myscreen := self.get(args.name) or {
|
||||
return error('couldnt start screen with name ${args.name}, was not found afterwards.\ncmd:${args.cmd}\nScreens found.\n${self.str()}')
|
||||
}
|
||||
|
||||
if args.attach {
|
||||
myscreen.attach()!
|
||||
}
|
||||
return myscreen
|
||||
}
|
||||
|
||||
// print list of screen screens
|
||||
pub fn (mut self ScreensFactory) exists(name string) bool {
|
||||
for mut screen in self.screens {
|
||||
if screen.name == name {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
pub fn (mut self ScreensFactory) get(name string) !Screen {
|
||||
for mut screen in self.screens {
|
||||
if screen.name == name {
|
||||
return screen
|
||||
}
|
||||
}
|
||||
// print_backtrace()
|
||||
return error('couldnt find screen with name ${name}\nScreens found.\n${self.str()}')
|
||||
}
|
||||
|
||||
pub fn (mut self ScreensFactory) start(name string) ! {
|
||||
mut s := self.get(name) or {
|
||||
return error("can't start screen with name:${name}, couldn't find.\nScreens found.\n${self.str()}")
|
||||
}
|
||||
s.start_()!
|
||||
for {
|
||||
self.scan()!
|
||||
mut s2 := self.get(name) or {
|
||||
return error('couldnt start screen with name ${name}, was not found in screen scan.\ncmd:\n${s.cmd}\nScreens found.\n${self.str()}')
|
||||
}
|
||||
if s2.pid > 0 {
|
||||
return
|
||||
}
|
||||
console.print_debug(s2.str())
|
||||
time.sleep(100000)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut self ScreensFactory) kill(name string) ! {
|
||||
if self.exists(name) {
|
||||
mut s := self.get(name) or { return }
|
||||
s.kill_()!
|
||||
}
|
||||
self.scan()!
|
||||
}
|
||||
|
||||
// print list of screen screens
|
||||
pub fn (mut self ScreensFactory) reset() ! {
|
||||
for mut screen in self.screens {
|
||||
screen.kill_()!
|
||||
}
|
||||
self.scan()!
|
||||
}
|
||||
|
||||
pub fn (mut self ScreensFactory) str() string {
|
||||
if self.screens.len == 0 {
|
||||
return 'No screens found.'
|
||||
}
|
||||
mut out := '# Screens\n'
|
||||
for s in self.screens {
|
||||
out += '${s}\n'
|
||||
}
|
||||
return out
|
||||
}
|
||||
13
lib/osal/screen/readme.md
Normal file
13
lib/osal/screen/readme.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# screen
|
||||
|
||||
```bash
|
||||
#to see sessions which have been created
|
||||
|
||||
screen -ls
|
||||
|
||||
There is a screen on:
|
||||
3230.test (Detached)
|
||||
|
||||
#now to attach to this screen
|
||||
screen -r test
|
||||
```
|
||||
142
lib/osal/screen/screen.v
Normal file
142
lib/osal/screen/screen.v
Normal file
@@ -0,0 +1,142 @@
|
||||
module screen
|
||||
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
import freeflowuniverse.herolib.osal
|
||||
import os
|
||||
import time
|
||||
|
||||
@[heap]
|
||||
struct Screen {
|
||||
mut:
|
||||
cmd string
|
||||
name string
|
||||
pid int
|
||||
state ScreenState
|
||||
// factory ?&ScreensFactory @[skip; str: skip]
|
||||
}
|
||||
|
||||
enum ScreenState {
|
||||
unknown
|
||||
detached
|
||||
}
|
||||
|
||||
// checks whether screen server is running
|
||||
pub fn (mut t Screen) is_running() !bool {
|
||||
panic('implement')
|
||||
// res := osal.exec(cmd: 'screen info', stdout: false, name: 'screen_info', raise_error: false) or {
|
||||
// panic('bug')
|
||||
// }
|
||||
// if res.error.contains('no server running') {
|
||||
// // console.print_debug(" TMUX NOT RUNNING")
|
||||
// return false
|
||||
// }
|
||||
// if res.error.contains('no current client') {
|
||||
// return true
|
||||
// }
|
||||
// if res.exit_code > 0 {
|
||||
// return error('could not execute screen info.\n${res}')
|
||||
// }
|
||||
return true
|
||||
}
|
||||
|
||||
pub enum ScreenStatus {
|
||||
unknown
|
||||
active
|
||||
inactive
|
||||
}
|
||||
|
||||
// Method to check the status of a screen process
|
||||
pub fn (self Screen) status() !ScreenStatus {
|
||||
panic('implement')
|
||||
// // Command to list screen sessions
|
||||
// cmd := 'screen -ls'
|
||||
// response := osal.execute_silent(cmd)!
|
||||
|
||||
// // Check if the screen session exists
|
||||
// if !response.contains(self.name) {
|
||||
// return .inactive
|
||||
// }
|
||||
|
||||
// // Command to send a dummy command to the screen session and check response
|
||||
// cmd_check := 'screen -S ${self.name} -X eval "stuff \\"\\003\\"; sleep 0.1; stuff \\"ps\\n\\""'
|
||||
// osal.execute_silent(cmd_check)!
|
||||
|
||||
// // Check if the process is running in the screen session
|
||||
// cmd_ps := 'screen -S ${self.name} -X hardcopy -h /tmp/screen_output; cat /tmp/screen_output | grep "${self.name}"'
|
||||
// ps_response := osal.execute_silent(cmd_ps)!
|
||||
|
||||
// return parse_screen_process_status(ps_response)
|
||||
}
|
||||
|
||||
// Function to parse screen process status output
|
||||
fn parse_screen_process_status(output string) ScreenStatus {
|
||||
lines := output.split_into_lines()
|
||||
for line in lines {
|
||||
if line.contains('SCREEN') || line.contains('PID') {
|
||||
return .active
|
||||
}
|
||||
}
|
||||
return .inactive
|
||||
}
|
||||
|
||||
fn (mut self Screen) kill_() ! {
|
||||
// console.print_debug('kill screen: ${self}')
|
||||
if self.pid == 0 || self.pid < 5 {
|
||||
return error("pid was <5 for ${self}, can't kill")
|
||||
}
|
||||
osal.process_kill_recursive(pid: self.pid)!
|
||||
res := os.execute('export TERM=xterm-color && screen -X -S ${self.name} kill > /dev/null 2>&1')
|
||||
if res.exit_code > 1 {
|
||||
return error('could not kill a screen.\n${res.output}')
|
||||
}
|
||||
time.sleep(100 * time.millisecond) // 0.1 sec wait
|
||||
os.execute('screen -wipe > /dev/null 2>&1')
|
||||
// self.scan()!
|
||||
}
|
||||
|
||||
// fn (mut self Screen) scan() ! {
|
||||
// mut f:=self.factory or {panic("bug, no factory attached to screen.")}
|
||||
// f.scan(false)!
|
||||
// }
|
||||
|
||||
pub fn (mut self Screen) attach() ! {
|
||||
cmd := 'screen -r ${self.pid}.${self.name}'
|
||||
osal.execute_interactive(cmd)!
|
||||
}
|
||||
|
||||
pub fn (mut self Screen) cmd_send(cmd string) ! {
|
||||
mut cmd2 := "screen -S ${self.name} -p 0 -X stuff \"${cmd} \n\" "
|
||||
if osal.is_osx() {
|
||||
cmd2 = "screen -S ${self.name} -p 0 -X stuff \"${cmd}\"\$'\n' "
|
||||
}
|
||||
res := os.execute(cmd2)
|
||||
if res.exit_code > 1 {
|
||||
return error('could not send screen command.\n${cmd2}\n${res.output}')
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut self Screen) str() string {
|
||||
green := console.color_fg(.green)
|
||||
yellow := console.color_fg(.yellow)
|
||||
reset := console.reset
|
||||
return ' - screen:${green}${self.name:-20}${reset} pid:${yellow}${self.pid:-10}${reset} state:${green}${self.state}${reset}'
|
||||
}
|
||||
|
||||
fn (mut self Screen) start_() ! {
|
||||
if self.pid != 0 {
|
||||
return
|
||||
}
|
||||
if self.name.len == 0 {
|
||||
return error('screen name needs to exist.')
|
||||
}
|
||||
if self.cmd == '' {
|
||||
self.cmd = '/bin/bash'
|
||||
}
|
||||
cmd := 'export TERM=xterm-color && screen -dmS ${self.name} ${self.cmd}'
|
||||
// console.print_debug(" startcmd:'${cmd}'")
|
||||
res := os.execute(cmd)
|
||||
// console.print_debug(res)
|
||||
if res.exit_code > 1 {
|
||||
return error('could not find screen or other error, make sure screen is installed.\n${res.output}')
|
||||
}
|
||||
}
|
||||
17
lib/osal/screen/screen_test.v
Normal file
17
lib/osal/screen/screen_test.v
Normal file
@@ -0,0 +1,17 @@
|
||||
module screen
|
||||
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
import freeflowuniverse.herolib.osal
|
||||
import os
|
||||
import time
|
||||
|
||||
pub fn testsuite_begin() ! {
|
||||
mut screen_factory := new(reset: true)!
|
||||
}
|
||||
|
||||
pub fn test_screen_status() ! {
|
||||
mut screen_factory := new()!
|
||||
mut screen := screen_factory.add(name: 'testservice', cmd: 'redis-server')!
|
||||
status := screen.status()!
|
||||
// assert status == .active
|
||||
}
|
||||
Reference in New Issue
Block a user