fake_cmd provides a simulated remote command line based on file communication to send commands from the client to the server for execution.
Project description
fake_cmd
fake_cmd provides a simulated remote command line based on file communication, in order to send commands from the client to the server for execution. It applies to situations where two computers cannot be connected through the network (which means ssh is impossible), but can be mounted onto the same hard disk.
Get Started
Installation
Requirements
slime_core is a necessary dependency, and install it as follows (Note that the version should be 0.0.1):
pip install slime-core==0.0.1
pexpect is a recommended dependency (if you run the server on a Unix platform):
pip install pexpect
Install fake_cmd
Install fake_cmd as follows:
pip install fake_cmd
Start the Server and the Client
On the server computer which you want to run your code on, start the server as follows:
from fake_cmd.core.server import Server
if __name__ == "__main__":
Server("/specify/a/hard/disk/path/here").run()
On the client, start the client as follows:
from fake_cmd.core.client import CLI
if __name__ == "__main__":
CLI("/same/path/as/the/server").run()
Alternatively, after installation you can start the server and client via commands:
# Start the server with address as a positional argument
fake-cmd-server /specify/a/hard/disk/path/here --max_cmds 8
# Start the client with address as a positional argument
fake-cmd-client /same/path/as/the/server --id_prefix abc
Usage
In fake_cmd, there is only one Server instance running at each address, and one Server can create multiple Sessions which are responsible for communicating with the Clients (and there is a one-to-one correspondence between Sessions and Clients). fake_cmd supports inner commands and command options for advanced usage, and you can simply use them in the Client CLI.
Inner Commands
help: Get the help document.exit: Shutdown the client and disconnect session.sid: Get the session id of the client.ls-session: List all the alive sessions.ls-cmd: List all the commands executing or queued.ls-back: List the background command of the current session.ls-server-version: Show the server version (for compatibility check).version_strict_on: Set the version strict to True.version_strict_off: Set the version strict to False.
Command Options
The command options can set advanced configurations when running the given command.
Usage
Required Syntax:
[Command options (as follows)] -- [Your real command]
Example:
inter --exec /bin/bash -- python -i
In the above example, inter --exec /bin/bash is the command options, and python -i is your real command to run on the server, -- serves as a delimiter to separate between the command options and the real command.
Supported Command Options
cmd: Run the command with advanced options. Usecmd -hto get more help in the Client.inter: Run the command in the interactive mode. Input is enabled. Useinter -hto get more help in the Client.pexpect: Run the command in an advanced interactive mode using the additional packagepexpect(Availability: Unix). Usepexpect -hto get more help.
Examples
In fake_cmd, if you run a command by directly entering the real command (e.g., ls) or using cmd options (e.g., cmd --exec /bin/bash -- ls), then the input is disabled, and you CANNOT send any input to the command running on the Session:
[fake_cmd XXX]$ python -i
# If you try to enter ``import random`` here, then nothing will happen.
>>> import random
If you use inter or pexpect (on Unix) to run the command, then the interactive mode is activated, and fake_cmd will read any of the input content from the client and send it to the command running on the Session:
# This is OK.
[fake_cmd XXX]$ inter -- python -i
>>> import random
>>> random.random()
0.8675832272860072
>>>
# This is also OK (on Unix).
[fake_cmd XXX]$ pexpect -- python
>>> import random
>>> random.random()
0.14142611546447192
>>>
NOTE: If you are starting a Server on a Unix platform, then we recommend you to activate the interactive mode using
pexpectrather thaninter, because the former provides more comprehensive functionality.
In fake_cmd, when you are running a command on the Session, the default behavior of Ctrl-C is sending different kill signals to the Session according to the number of times Ctrl-C is pressed (See Kill the Running Command for more details). However, in the interactive mode, you may only want to send keyboard interrupts to the command by pressing Ctrl-C rather than killing it (for example, if you run inter -- python -i, you may press Ctrl-C to interrupt the Python code rather than killing the Python itself). To solve this, you can run the command using the --kill_disabled option:
[fake_cmd XXX]$ pexpect --kill_disabled -- python
# Wow, ``Ctrl-C`` can now interrupt the Python code rather than killing Python itself!
>>> import time
>>> time.sleep(114514)
^CTraceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyboardInterrupt
>>> time.sleep(1919810)
^CTraceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyboardInterrupt
NOTE: If you run a command in the interactive mode using
inter, you should explicitly activate interactive mode of the command (e.g., usingpython -irather thanpython, using/bin/bash -irather than/bin/bash, etc.). While if you usepexpect, just run the command as usual (e.g.,python,/bin/bash, etc.).
WARNING: Here is one of the reasons that we recommend you to use
pexpectrather thaninteron Unix:In our tests, if you run bash using
inter --kill_disabled -- /bin/bash -i, and you run another command in the bash, then you will be unable to kill the command usingCtrl-C, maybe because the SIGINT signal (i.e., the keyboard interrupt) can not be passed to the command. While if you usepexpect --kill_disabled -- /bin/bash, which starts a pseudo terminal to run the command, thenCtrl-Cwill be successfully sent to the command just like the user really pressesCtrl-Cin the command line.The following example shows this problem:
[fake_cmd XXX]$ inter --kill_disabled -- /bin/bash -i # Now enter the bash command line. # The keyboard interrupt won't kill the ``sleep 114514`` command, and you can only kill it in another client using ``kill -9 pid``. [xxx ~]$ sleep 114514 Keyboard Interrupt (Interactive Input). Keyboard Interrupt (Interactive Input). Keyboard Interrupt (Interactive Input). # Recommended on Unix. [fake_cmd XXX]$ pexpect --kill_disabled -- /bin/bash # Now enter the bash command line. [xxx ~]$ sleep 1919810 Keyboard Interrupt (Interactive Input). # Yeah, you successfully killed it. [xxx ~]$
NOTE:
intermay fail to send the input when the command requires entering a password (e.g.,sudo), whilepexpectcan achieve this (the reasons are discussed in Going Deeper into the Command Options).WARNING: The password you enter will not be hidden by
fake_cmd, becausefake_cmdwill never know when the command requires a password, and it treats all inputs as regular ones. Example:[fake_cmd XXX]$ pexpect -- sudo ls Password:Oh, my password will not be hidden here. xxx (The output of ``ls``)
Going Deeper into the Command Options (Optional Reading)
If you run a command by directly entering it in the fake_cmd or using cmd or inter options, the Session will start the command using Popen in the standard Python library subprocess. It can only redirect the input and output streams of the command to a pipe or a specified file, so it does not simulate a command line in the true sense, and in some cases it may fail to control the behavior of the command (for example, it fails to send a password to the command when you are running sudo).
Different from Popen, pexpect starts a new command by creating a pseudo terminal using pty.fork, which can be seen as a real command line by the running command, and it supports more features such as entering a password, sending Ctrl-C to the command line (just like a real user does), etc.
Kill the Running Command
If you are directly entering a command in fake_cmd, using cmd or --kill_disabled is not specified in the interactive
mode, the number of times Ctrl+C is pressed represents different behaviors:
- (1): Send keyboard interrupt to the command (SIGINT signal).
- (2): Terminate the command (SIGTERM signal).
- (3): Kill the command (SIGKILL signal on Unix, and SIGTERM signal on Windows).
- (>=4): Do not wait until the command is terminated, and put the command to the background (and then you can use
ls-backto check it, or manually usekill -9 pidto kill it).
If --kill_disabled is specified in the interactive mode, one Ctrl+C corresponds to one keyboard interrupt sent to the command, and you may need to manually exit the command according to different commands (e.g., use exit() in the Python interactive mode, and use exit in the /bin/bash, etc.).
Danger Zone
server_shutdown: Shutdown the whole server. NOTE: The server can be shutdown by any of the Clients, without any authorization required. When shutdown is executed, the Server will terminate all the commands and destroy all the sessions. BE CAREFUL TO USE IT!!!
Other Things to Note
About the Command-Line State
In fake_cmd, each command you enter is executed separately, so the command-line state cannot be preserved between the commands. Example:
[fake_cmd XXX]$ pwd
/a/b/c
[fake_cmd XXX]$ cd ../
[fake_cmd XXX]$ pwd
# NOTE: the output of ``pwd`` here is still ``/a/b/c``, because the previous ``cd`` command and the ``pwd`` command are executed separately.
/a/b/c
[fake_cmd XXX]$ cd ../; pwd
# The output of ``pwd`` becomes ``/a/b`` here, because the ``cd`` command and the ``pwd`` command are executed in one command. Due to this, you can put all the commands in one shell file, and run it using ``sh``, ``/bin/bash``, etc.
/a/b
While, if you run bash using pexpect (or inter), then in bash the state can be preserved, because the bash is executed once by fake_cmd, and then it keeps running in the interactive mode. Example:
[fake_cmd XXX]$ pexpect --kill_disabled -- /bin/bash
# Now enter the bash command line.
[xxx c]$ pwd
/a/b/c
[xxx c]$ cd ../
[xxx b]$ pwd
# The state can be preserved by bash.
/a/b
# You can even use conda here.
[xxx b]$ conda init bash
[xxx b]$ source ~/.bashrc
[xxx b]$ conda activate base
# Yeah, conda activated successfully!
(base) [xxx b]$
One Display Bug that Cannot be Eliminated
fake_cmd only simulates a remote command line by displaying the remote output in the Client and sending the input from the Client to the Session, and it doesn't implement low-level command line interfaces as ssh does. Because of this, there will be messed-up display in the interactive mode (especially when the readline module is enabled), for fake_cmd doesn't exactly know what the input prompt is in the Session command and simply uses input() with an empty prompt. Example:
[fake_cmd XXX]$ pexpect --kill_disabled -- /bin/bash
# Now enter the bash command line.
[xxx ~]$
# If you input something in the bash command line and delete it using backspace, then the whole line will be deleted (including the display content ``[xxx ~]$ ``)
[xxx ~]$ enter something here 114514
# Then delete using backspace
█ (Oops, the whole line is deleted)
# Further, if you input something that is longer than the command line width, messed-up display also occurs. One way to solve this problem (not quite as elegantly) is to press ``Ctrl-D`` (raise an EOFError) to start a new line.
[xxx ~]$ EOF (Interactive Input).
█ (Now I can input something here on a new line and no messed-up display will occur, because ``input()`` is used with an empty prompt, which aligns perfectly with the empty new line)
License
fake_cmd uses an MIT license, as found in the LICENSE file.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file fake_cmd-0.0.8.tar.gz.
File metadata
- Download URL: fake_cmd-0.0.8.tar.gz
- Upload date:
- Size: 52.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
72cfc220e286b6bfee3757a24db811e55071db1f6337c307bf305a1109ca4aeb
|
|
| MD5 |
cddf28c8d8e255a0d40c710bb1ef38d9
|
|
| BLAKE2b-256 |
cfe91fdb541a709e87e15f5f904ac719e8a162488b47479e49db79ac70b3a2b7
|
File details
Details for the file fake_cmd-0.0.8-py3-none-any.whl.
File metadata
- Download URL: fake_cmd-0.0.8-py3-none-any.whl
- Upload date:
- Size: 53.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
374070bcdc52d24e9657e2f195fcb4da80099fd43be497eddceb8d7fdfd6c52f
|
|
| MD5 |
ddb31c1f67dcb3009ab6316fb4b35012
|
|
| BLAKE2b-256 |
8aa8e210c32a65a25c8b91c0eb8ca995a77a6890edc0809ebc2c1bc19975c6c7
|