Update article

This commit is contained in:
Raven Scott 2024-09-18 19:42:13 -04:00
parent 099c9f138b
commit bdc4cdaf77

View File

@ -498,6 +498,159 @@ The menu is dynamically generated, allowing users to make their selection. If th
This safeguard prevents users from accidentally deleting important containers or data, which is especially useful in environments where multiple users or containers are being managed.
# Executing Shell Commands Using Discord Bot (Non-Interactive Execution)
The platforms ability to execute commands non-interactively via Discord is a game-changer for container management and remote server operations. This powerful feature lets users run commands, manage files, check system statuses, and more—all from a simple Discord interface, without needing further interaction after issuing a command. In this post, we will dive into how the system works, highlighting some special custom-coded commands like `cd`, `pwd`, and `ls`, and how the platform ensures non-interactive command execution.
### Non-Interactive Command Execution Overview
Non-interactive execution means that once a user submits a command through the bot, it completes without asking for additional input. This is incredibly useful when dealing with long-running processes or package installations, where user input (like confirmations) is usually required. The bot takes care of everything—from preparing the command, running it, and presenting the result.
The bot executes commands inside Docker containers specific to each user, providing isolated environments. These containers are used to execute commands non-interactively, meaning once you send the command, the bot does the rest.
### Command Handling Flow
The bot's `/x` command allows users to execute commands within their container. Heres the general structure of how it works:
```javascript
module.exports = {
name: "x",
description: "Execute a command non-interactively.",
options: [
{
name: "cmd",
description: "Command to Execute",
required: true,
type: 3 // STRING type
}
],
run: async (client, interaction) => {
let sshSurfID = await getUserContainerID(interaction.user.id);
let userPWD = await getUserPWD(interaction.user.id);
if (!sshSurfID) {
await interaction.editReply("You don't have a container currently. Please generate one using /generate.");
return;
}
let commandToRun = interaction.options.get("cmd").value;
// Handle special cases (custom commands like cd, pwd, and ls)
commandToRun = handleCustomCommands(commandToRun, userPWD, sshSurfID, interaction);
// Run the command in a non-interactive manner within the user's container
executeCommandInContainer(sshSurfID, userPWD, commandToRun, interaction);
}
};
```
### Custom Coded Commands: `cd`, `pwd`, `ls`
In addition to executing common system commands like `apt`, `yum`, or `neofetch`, the platform includes custom implementations for commands like `cd`, `pwd`, and `ls`. These are custom coded to work seamlessly with the platform, ensuring non-interactive behavior.
#### `cd` (Change Directory)
The `cd` command allows users to navigate through the file system within their container. Since changing directories is fundamental for any file operation, the platform implements `cd` in a custom way.
The custom `cd` command ensures that the current working directory is updated on the platform, and it intelligently handles edge cases like moving up (`cd ..`), moving to a root directory (`cd /`), or using the home directory shortcut (`cd ~`). This is all handled behind the scenes, and the updated directory is stored in the users session for future commands.
Heres a simplified view of the custom `cd` logic:
```javascript
if (commandToRun.startsWith("cd")) {
let newDirectory = handleCdCommand(commandToRun, userPWD); // Handles various cases like `..`, `~`, and `/`
updatePWD(newDirectory, sshSurfID); // Update user's current directory
interaction.editReply(`Directory changed to: ${newDirectory}`);
}
```
#### `pwd` (Print Working Directory)
The `pwd` command is another custom implementation. Instead of executing the Linux `pwd` command inside the container, the bot retrieves the user's current working directory directly from the platforms stored session. This ensures faster responses and removes the need for running the command in the container itself.
```javascript
if (commandToRun === "pwd") {
interaction.editReply(`\`\`\`${userPWD}\`\`\``);
}
```
This custom `pwd` command guarantees that the bot provides accurate feedback on the user's current directory, without needing to execute a process inside the container.
#### `ls` (List Directory Contents)
The `ls` command is handled in a slightly more complex way because it needs to interact with the file system to show directory contents. The platform uses Docker's `exec` feature to run the `ls` command inside the container, while still ensuring non-interactive execution.
```javascript
if (commandToRun.startsWith("ls")) {
// Execute ls inside the user's container non-interactively
customerContainer.exec(['/bin/bash', '-c', `cd ${userPWD} && ls -lah`], { stdout: true, stderr: true }, (err, out) => {
interaction.editReply(`\`\`\`${out.stdout}\`\`\``);
});
}
```
The result is that `ls` works just like it would in a standard Linux environment, listing directory contents in a user-friendly way.
### Handling Non-Interactive Execution
Non-interactive commands are a core feature of this platform. Commands that typically require user input (like `apt install`) are automatically modified to run without interaction. For example, if a user runs `apt install`, the bot adds the `-y` flag to ensure the process runs without requiring further confirmation:
```javascript
if (commandToRun.startsWith("apt install") || commandToRun.startsWith("yum install")) {
if (!commandToRun.includes("-y")) {
commandToRun += " -y"; // Automatically add non-interactive flag
}
}
```
This customization ensures that no matter what command you issue, it will complete without stopping to ask for confirmation or additional input.
### Executing Commands in the Container
Once the command is prepared, the bot uses Docker to execute it inside the user's container. This is done non-interactively, meaning the user doesnt need to stay engaged for the command to finish.
Heres how the bot executes commands inside the container:
```javascript
const customerContainer = docker.getContainer(sshSurfID);
customerContainer.exec(['/bin/bash', '-c', `cd ${userPWD} && ${commandToRun}`], { stdout: true, stderr: true }, (err, out) => {
if (err || !out) {
interaction.editReply("```Your container either needs to be generated or is not running.```");
return;
}
if (out.inspect.ExitCode !== 0) {
interaction.editReply(`\`\`\`Error: ${out.stderr}\`\`\``);
} else {
interaction.editReply(`\`\`\`${out.stdout}\`\`\``);
}
});
```
The command is executed within the container, and the result (either success or failure) is sent back to the user in Discord.
### Output Management
Command outputs are returned directly in Discord. However, if the output is too long to fit in a single message, the platform uses a service like `dpaste` to upload the output and return a link to the user:
```javascript
if (out.stdout.length > 2020) {
fs.writeFile('/tmp/paste', `Command: ${commandToRun}\n${out.stdout}`, err => {
if (err) console.error(err);
});
cmd("sleep 2; cat /tmp/paste | dpaste").then(pasteout => {
interaction.editReply(`The command output was too large for Discord. Check it here: ${pasteout.stdout}`);
});
} else {
interaction.editReply(`\`\`\`${out.stdout}\`\`\``);
}
```
This ensures that even large outputs can be managed efficiently and that users always receive the results of their commands.
The platforms ability to run commands non-interactively via Discord is incredibly powerful. With custom-coded commands like `cd`, `pwd`, and `ls`, users can easily navigate and interact with their containerized environments. The platform's non-interactive approach ensures that commands run to completion without requiring additional input, making it a smooth experience for users managing servers and systems remotely.
By leveraging Docker, REST logging, and thoughtful command handling, the platform delivers a flexible and secure way for users to run commands, all within a familiar interface like Discord.
### Container Destruction
Once the user confirms that they want to proceed, the bot performs the actual destruction of the container. This is done by stopping and removing the container using Dockers command-line interface.