{"id":19963301,"url":"https://github.com/advrhumanoids/concert_launcher","last_synced_at":"2026-03-12T16:32:59.461Z","repository":{"id":222149418,"uuid":"756402207","full_name":"ADVRHumanoids/concert_launcher","owner":"ADVRHumanoids","description":"A minimal process launching automation tool based on YAML and TMUX","archived":false,"fork":false,"pushed_at":"2025-06-20T10:56:14.000Z","size":121,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-09-09T00:24:53.386Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ADVRHumanoids.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2024-02-12T15:45:30.000Z","updated_at":"2025-06-20T10:56:18.000Z","dependencies_parsed_at":"2024-03-05T13:39:41.872Z","dependency_job_id":"7399743f-3717-4c5a-9422-7d36a1959b21","html_url":"https://github.com/ADVRHumanoids/concert_launcher","commit_stats":null,"previous_names":["advrhumanoids/concert_launcher"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ADVRHumanoids/concert_launcher","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ADVRHumanoids%2Fconcert_launcher","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ADVRHumanoids%2Fconcert_launcher/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ADVRHumanoids%2Fconcert_launcher/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ADVRHumanoids%2Fconcert_launcher/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ADVRHumanoids","download_url":"https://codeload.github.com/ADVRHumanoids/concert_launcher/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ADVRHumanoids%2Fconcert_launcher/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30433024,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-12T14:34:45.044Z","status":"ssl_error","status_checked_at":"2026-03-12T14:09:33.793Z","response_time":114,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-13T02:15:32.167Z","updated_at":"2026-03-12T16:32:59.429Z","avatar_url":"https://github.com/ADVRHumanoids.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Concert Launcher\n\n## Overview\n\nThe Concert Launcher serves as the core process management system for robotics software stacks, providing:\n\n- **Multi-environment execution**: Run processes locally, on remote machines via SSH, or inside Docker containers\n- **Process management**: Start, stop, monitor, and check the status of processes\n- **Variants and configurations**: Define different execution configurations for the same process\n- **Parametrization**: Customize process execution with context parameters\n- **Robust execution**: Uses `tmux` for reliable background process management\n- **Real-time monitoring**: Stream process output and monitor process status\n\n## Core Components\n\n### concert_launcher/src/concert_launcher/executor.py\n\nThe `executor.py` module is the heart of the Concert Launcher system. It implements the `Executor` class, which contains the following core functionality:\n\n1. **Configuration Management**:\n   - Parses the `launcher_config.yaml` file, resolving aliases and handling default parameters\n   - Understands variant configurations and applies them to process definitions\n   - Constructs final command strings with parameter substitution and variant modifications\n\n2. **Environment Handling**:\n   - Supports local execution, remote execution via SSH, and containerized execution in Docker\n   - Handles necessary command wrapping for Docker execution (e.g., `docker exec -it \u003ccontainer\u003e bash -ic \"\u003ccmd\u003e\"`)\n   - Provides a consistent process management interface regardless of execution environment\n\n3. **SSH Integration**:\n   - Uses the `asyncssh` library to establish asynchronous SSH connections to remote machines\n   - Manages SSH sessions effectively to avoid connection leaks or timeouts\n   - Supports various authentication methods (password, key-based)\n\n4. **tmux Integration**:\n   - Launches processes within tmux sessions on target machines for persistence\n   - Creates dedicated tmux windows for each process with appropriate naming\n   - Uses tmux commands to start, monitor, and terminate processes reliably\n   - Enables processes to continue running even if the SSH connection drops\n\n5. **Process Management**:\n   - **Start**: Launches processes with appropriate environment setup and variant configurations\n   - **Stop/Kill**: Sends signals (SIGINT for graceful, SIGKILL for forced) to processes\n   - **Status**: Checks if processes are running, ready, or stopped\n   - **Ready Check**: Periodically executes custom commands to verify if a process is fully operational\n   - **Process Tree**: Retrieves hierarchical process information for debugging\n\n6. **Output Streaming**:\n   - Provides asynchronous streaming of process stdout/stderr\n   - Uses efficient techniques (like `tail -f`) to monitor process output\n   - Supports filtering and formatting of process output\n\n7. **Event Notification**:\n   - Implements a callback mechanism for notifying callers about process events\n   - Generates detailed status updates during process lifecycle (starting, checking readiness, ready, error)\n\n### Asynchronous Implementation\n\nThe Executor is implemented using Python's `asyncio` framework, allowing for:\n\n- Non-blocking I/O operations (especially important for SSH and process monitoring)\n- Concurrent management of multiple processes\n- Efficient resource utilization\n- Responsive status checking and event notification\n\n## Configuration Format\n\nThe Concert Launcher uses a flexible YAML configuration format. Here's an example of it, that can be find in Kyon-Config repo [Kyon-Config](https://github.com/ADVRHumanoids/kyon_config):\n\n```yaml\ncontext:\n  session: my_session       # Default tmux session name for process grouping\n  params:                   # Global parameters accessible via {param_name} substitution\n    hw_type: default_type   # Example parameter used in commands\n  .defines:                 # YAML Anchors for reusable aliases\n    - \u0026local localhost      # Define local machine alias\n    - \u0026remote user@host     # Define remote SSH target\n    - \u0026docker_xeno container_name  # Define Docker container name\n\n# Process Definitions (each top-level key except 'context' defines a process)\nprocess_name:\n  cmd: executable --param {hw_type}  # Command with parameter substitution\n  machine: *remote          # WHERE: Run on machine referenced by 'remote' alias (via SSH)\n  docker: *docker_xeno      # HOW: Run inside Docker container referenced by 'docker_xeno'\n  ready_check: test_command # Command to verify process is ready (exit code 0 = ready)\n  variants:                 # Alternative configurations\n    simple_flag:            # Simple flag variant (adds to command)\n      cmd: \"{cmd} --verbose\"  # Appends to base command using {cmd} as placeholder\n    option_group:           # Group of mutually exclusive options (like radio buttons)\n      - option1:            # Option name\n          params:           # Option-specific parameters\n            hw_type: type1  # Overrides the global hw_type for this variant\n      - option2:\n          params:\n            hw_type: type2\n```\n\n### Process Execution Flow\n\nWhen executing a process (`execute_process()`), the Executor:\n\n1. Retrieves the process definition from the configuration\n2. Applies selected variants to determine the final command and parameters\n3. Establishes connection to the target machine (local or via SSH)\n4. Constructs the appropriate execution command based on environment:\n   - For local: executes directly\n   - For SSH: wraps command appropriately\n   - For Docker: wraps with `docker exec` command\n5. Uses tmux to launch the process in a dedicated window:\n   ```bash\n   tmux new-window -d -n process_name -t session: 'command'\n   ```\n6. Captures process output to a temporary file for monitoring\n7. If a `ready_check` is defined, periodically executes it until success\n8. Updates process status and notifies via events/callbacks\n\n### Process Monitoring and Status\n\nThe Executor provides comprehensive monitoring capabilities:\n\n- **Status Checking**: Uses tmux commands to check if a process is still running:\n  ```bash\n  tmux list-windows -t session: -F '#{window_name} #{pane_pid}'\n  ```\n\n- **Process Tree**: Retrieves the full process tree for debugging:\n  ```bash\n  pstree -p $(tmux list-panes -t session:window -F '#{pane_pid}')\n  ```\n\n- **Output Streaming**: Watches process output in real-time:\n  ```bash\n  tail -f /tmp/process_output.log\n  ```\n\n## API Reference\n\n```python\nfrom concert_launcher.executor import Executor\n\n# Initialize with configuration file\nexecutor = Executor(\"launcher_config.yaml\")\n\n# Execute a process with variants\nawait executor.execute_process(\n    \"process_name\",           # Process name as defined in config\n    variants=[\"option1\"],     # Selected variants\n    on_event=callback_func    # Optional callback for status events\n)\n\n# Kill a process\nawait executor.kill(\n    \"process_name\",           # Process to terminate\n    graceful=True,            # True for SIGINT, False for SIGKILL\n    on_event=callback_func    # Optional event callback\n)\n\n# Check process status\nstatus = await executor.status(\"process_name\")\n# Returns: 0 (Stopped), 1 (Running), 2 (Ready), -1 (Error)\n\n# Get process tree\npstree = await executor.pstree(\"process_name\")\n# Returns: String representation of process hierarchy\n\n# Stream process output\nasync for line in executor.watch(\"process_name\"):\n    print(line)  # Process each line of output\n\n# Check all processes\nall_status = await executor.status()\n# Returns: Dictionary mapping process names to status codes\n```\n\n## Event Notification System\n\nThe Executor implements an event notification system through callbacks. When provided with an `on_event` function, it sends detailed status events during process lifecycle:\n\n```python\nasync def on_launcher_event(event_type, process_name, message, level=0):\n    \"\"\"\n    Callback for launcher events.\n    \n    Args:\n        event_type: Type of event (start, ready_check, ready, error, kill)\n        process_name: Name of the process\n        message: Detailed message about the event\n        level: Severity level (0=info, 1=warning, 2=error)\n    \"\"\"\n    print(f\"[{process_name}] {event_type}: {message}\")\n\n# Use with execute_process\nawait executor.execute_process(\"my_process\", on_event=on_launcher_event)\n```\n\nTypical events include:\n- \"Connecting via SSH...\"\n- \"Starting process...\"\n- \"Checking readiness...\"\n- \"Process ready\"\n- \"Error: Ready check failed\"\n- \"Process killed\"\n\n## Integration with Other Systems\n\nThe Concert Launcher is designed to be used as a library by other applications. Common integration patterns include:\n\n### Web Server Integration\n\n```python\n# Example integration with aiohttp web server\nfrom aiohttp import web\nfrom concert_launcher.executor import Executor\n\nclass LauncherServer:\n    def __init__(self, config_path):\n        self.executor = Executor(config_path)\n        self.app = web.Application()\n        self.setup_routes()\n        \n    def setup_routes(self):\n        self.app.router.add_get('/process/list', self.handle_process_list)\n        self.app.router.add_put('/process/{name}/command/{command}', self.handle_command)\n        \n    async def handle_process_list(self, request):\n        processes = self.executor.get_processes()\n        status = await self.executor.status()\n        return web.json_response({\n            'processes': processes,\n            'status': status\n        })\n        \n    async def handle_command(self, request):\n        name = request.match_info['name']\n        command = request.match_info['command']\n        \n        if command == 'start':\n            data = await request.json()\n            variants = data.get('variants', [])\n            await self.executor.execute_process(name, variants)\n        elif command == 'stop':\n            await self.executor.kill(name, graceful=True)\n            \n        return web.json_response({'success': True})\n```\n\n## Installation\n\nTailored to @alaurenzi 's laptop machine setup !\n\n```bash\npip install -e .\ncd config/example_alaurenzi  # a folder containing launcher.yaml\nconcert_launcher run cartesio  # run cartesio and its dependencies\nconcert_launcher mon  # spawn tmux monitoring session on local machine\nconcert_launcher status  # print process tree\nconcert_launcher kill [proc_name]  # kill proc_name (or all)\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadvrhumanoids%2Fconcert_launcher","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fadvrhumanoids%2Fconcert_launcher","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadvrhumanoids%2Fconcert_launcher/lists"}