Security News
Research
Data Theft Repackaged: A Case Study in Malicious Wrapper Packages on npm
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
View output of multiple processes, in parallel, in the console, with an interactive TUI
View output of multiple processes, in parallel, in the console, with an interactive TUI
pip install multiplex
# or better yet
pipx install multiplex
Python 3.7 or greater is required.
mp \
'./some-long-running-process.py --zone z1' \
'./some-long-running-process.py --zone z2' \
'./some-long-running-process.py --zone z3'
You can achive the same effect using Python API like this:
from multiplex import Multiplex
mp = Multiplex()
for zone in ['z1', 'z2', 'z3']:
mp.add(f"./some-long-running-process.py --zone {zone}")
mp.run()
my-script.sh
:
#!/bin/bash -e
echo Hello There
export REPO='git@github.com:dankilman/multiplex.git'
mp 'git clone $REPO'
mp 'pyenv virtualenv 3.8.5 multiplex-demo && pyenv local multiplex-demo'
cd multiplex
mp 'poetry install'
mp 'pytest tests'
mp @ Goodbye -b 0
And then running:
mp ./my-script.sh -b 7
An output similar to the first example can be achieved from a single process using the Python Controller API.
import random
import time
import threading
from multiplex import Multiplex, Controller
CSI = "\033["
RESET = CSI + "0m"
RED = CSI + "31m"
GREEN = CSI + "32m"
BLUE = CSI + "34m"
MAG = CSI + "35m"
CYAN = CSI + "36m"
mp = Multiplex()
controllers = [Controller(f"zone z{i+1}", thread_safe=True) for i in range(3)]
for controller in controllers:
mp.add(controller)
def run(index, c):
c.write(
f"Starting long running process in zone {BLUE}z{index}{RESET}, "
f"that is not really long for demo purposes\n"
)
count1 = count2 = 0
while True:
count1 += random.randint(0, 1000)
count2 += random.randint(0, 1000)
sleep = random.random() * 3
time.sleep(sleep)
c.write(
f"Processed {RED}{count1}{RESET} orders, "
f"total amount: {GREEN}${count2}{RESET}, "
f"Time it took to process this batch: {MAG}{sleep:0.2f}s{RESET}, "
f"Some more random data: {CYAN}{random.randint(500, 600)}{RESET}\n"
)
for index, controller in enumerate(controllers):
thread = threading.Thread(target=run, args=(index+1, controller))
thread.daemon = True
thread.start()
mp.run()
Type ?
to toggle the help screen.
In short, they solve different problems.
tmux
is a full blown terminal emulator multiplexer.
multiplex
on the other hand, tries to optimize for a smooth experience in navigating output from several sources.
tmux
doesn't have any notion of scrolling panes. That is to say, the layout contains all panes at any
given moment (unless maximized).
In multiplex
, current view will display boxes that fit current view, but you can have many more,
and move around boxes using less
inspired keys such as j
, k
, g
, G
, etc...
Another aspect is that keybindigs for moving around are much more ergonomic (as they are in less
) because
multiplex
is not a full terminal emulator, so it can afford using single letter keyboard bindings (e.g. g
for
go to beginning)
FAQs
View output of multiple processes, in parallel, in the console, with an interactive TUI
We found that multiplex demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Research
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Research
Security News
Attackers used a malicious npm package typosquatting a popular ESLint plugin to steal sensitive data, execute commands, and exploit developer systems.
Security News
The Ultralytics' PyPI Package was compromised four times in one weekend through GitHub Actions cache poisoning and failure to rotate previously compromised API tokens.