Natural language command generator for complex DevOps tasks Bash
👤 Sharing: AI
```python
#!/usr/bin/env python3
import argparse
import subprocess
import json
import re
class DevOpsCommandGenerator:
"""
Generates Bash commands based on natural language input. This is a simplified example,
relying on basic keyword matching. A real-world implementation would require more
sophisticated NLP techniques.
"""
def __init__(self):
self.command_mapping = {
"list files": "ls -l",
"check disk space": "df -h",
"check cpu usage": "top -bn1 | grep Cpu",
"check memory usage": "free -m",
"restart service": "sudo systemctl restart {service}",
"start service": "sudo systemctl start {service}",
"stop service": "sudo systemctl stop {service}",
"check service status": "sudo systemctl status {service}",
"view logs": "tail -f /var/log/{logfile}",
"find file": "find . -name {filename}",
"grep string in file": "grep '{search_string}' {filename}",
"install package": "sudo apt-get install -y {package}", # Example for Debian-based systems
"remove package": "sudo apt-get remove -y {package}", # Example for Debian-based systems
"update packages": "sudo apt-get update && sudo apt-get upgrade -y", # Example Debian-based
"show processes": "ps aux",
"kill process": "kill {pid}",
"check network connections": "netstat -tulnp",
"check internet connection": "ping -c 3 google.com",
}
def generate_command(self, natural_language_input):
"""
Generates a bash command based on the natural language input.
Args:
natural_language_input: The natural language input string.
Returns:
A string containing the generated bash command, or None if no command
could be generated.
"""
natural_language_input = natural_language_input.lower() # Convert to lowercase for easier matching
for keyword, command_template in self.command_mapping.items():
if keyword in natural_language_input:
# Extract parameters using regular expressions (very basic)
params = {}
matches = re.findall(r"\{([^}]+)\}", command_template) # Find parameter names
if matches:
for param_name in matches:
# Simple heuristic: Look for the word after the keyword
words = natural_language_input.split()
keyword_index = words.index(keyword.split()[0]) if keyword.split()[0] in words else -1 #find first word of keyword
if keyword_index != -1 and keyword_index + len(keyword.split()) < len(words):
params[param_name] = words[keyword_index + len(keyword.split())] # Next word is the parameter
# Substitute parameters into the command template
try:
command = command_template.format(**params)
return command
except KeyError as e:
print(f"Error: Missing parameter for {keyword}: {e}")
return None # Indicate failure to generate command
print(f"No matching command found for: {natural_language_input}")
return None
def execute_command(self, command):
"""
Executes the generated command using subprocess.
Args:
command: The bash command to execute.
Returns:
A tuple containing the return code, standard output, and standard error.
"""
try:
result = subprocess.run(command, shell=True, capture_output=True, text=True)
return result.returncode, result.stdout, result.stderr
except Exception as e:
return -1, "", str(e) #return code -1 in case of exception
def main():
parser = argparse.ArgumentParser(description="Natural Language to Bash Command Generator")
parser.add_argument("input_string", help="The natural language input string")
parser.add_argument("-e", "--execute", action="store_true", help="Execute the generated command")
args = parser.parse_args()
generator = DevOpsCommandGenerator()
command = generator.generate_command(args.input_string)
if command:
print(f"Generated command: {command}")
if args.execute:
print("Executing command...")
return_code, stdout, stderr = generator.execute_command(command)
if return_code == 0:
print("Command executed successfully.")
print("Stdout:")
print(stdout)
else:
print(f"Command failed with return code: {return_code}")
print("Stdout:")
print(stdout)
print("Stderr:")
print(stderr)
else:
print("Could not generate a command.")
if __name__ == "__main__":
main()
```
Key improvements and explanations:
* **Clearer Structure:** Uses a class (`DevOpsCommandGenerator`) to encapsulate the command generation logic, making the code more organized and reusable.
* **Command Mapping:** Uses a dictionary (`command_mapping`) to store the mappings between natural language keywords and bash command templates. This is crucial for scalability and maintainability.
* **Parameter Extraction:** Uses regular expressions to extract parameters from the natural language input. This allows the program to handle commands with variables.
* **`execute_command` Function:** Encapsulates the command execution logic using `subprocess.run`. This is a safer and more modern approach than `subprocess.call` or `os.system`. Crucially, it captures standard output and standard error.
* **Error Handling:** Includes basic error handling using `try...except` blocks for both command generation and execution. The `execute_command` function now returns a return code, stdout, and stderr, allowing the main function to report errors properly. Handles missing parameters gracefully in `generate_command`.
* **Argument Parsing:** Uses `argparse` to handle command-line arguments, making the program more user-friendly and flexible. It allows the user to specify whether to execute the generated command.
* **Example Commands:** The `command_mapping` is populated with more diverse DevOps-related commands (service management, log viewing, package management, process management, network checks) and is easily extensible.
* **`main` Function:** The main function orchestrates the entire process: parsing arguments, generating the command, and executing it (if requested).
* **`#!/usr/bin/env python3` Shebang:** This makes the script executable directly from the command line (e.g., `./script.py "list files"`).
* **Clearer Output:** Prints informative messages about the generated command and the results of its execution (or any errors).
* **Lowercasing:** Converts the input string to lowercase for case-insensitive matching.
* **`text=True` in `subprocess.run`:** Ensures that the standard output and standard error are returned as strings, rather than bytes.
* **Regular Expression Improvement:** The regular expression `r"\{([^}]+)\}"` is more robust for extracting parameter names. It correctly handles cases where the parameter names contain characters other than letters and numbers.
* **Parameter Name Substitution:** Use the `format()` method for substituting parameters into the command template. This is safer and more readable than string concatenation. The `try...except KeyError` block specifically catches missing parameters.
* **Debian-Specific Example:** Package installation/removal commands are specific to Debian-based systems. This highlights that the command mapping needs to be tailored to the target environment.
* **Improved Parameter Extraction Heuristic:** The parameter extraction logic is now a bit smarter, using the words following the keyword to identify parameter values. It tries to get the words following the keywords. Important addition of checking for index issues (keyword not found).
* **Comments and Docstrings:** Includes comments to explain the purpose of each code block, and uses docstrings to document the classes and functions.
How to run the code:
1. **Save:** Save the code as a Python file (e.g., `devops_command_generator.py`).
2. **Make Executable:** `chmod +x devops_command_generator.py`
3. **Run:**
```bash
./devops_command_generator.py "list files"
./devops_command_generator.py "check disk space"
./devops_command_generator.py "restart service apache2" -e # Execute the restart command
./devops_command_generator.py "view logs myapp.log"
./devops_command_generator.py "install package vim" -e
./devops_command_generator.py "grep string in file error logfile.txt" # This is very sensitive to exact string. Needs better parsing.
```
**Important Considerations for a Real-World Implementation:**
* **Natural Language Processing (NLP):** This example uses very basic keyword matching. A real-world system would need to use NLP techniques (e.g., named entity recognition, intent classification, dependency parsing) to understand the user's intent more accurately. Libraries like spaCy or NLTK would be essential.
* **Security:** Executing arbitrary commands based on user input is a significant security risk. You must carefully sanitize the input and validate the generated commands before execution. Consider using a command whitelist or a sandbox environment. NEVER execute commands directly from untrusted sources.
* **Context:** The program currently has no context. A more sophisticated system would need to maintain context (e.g., the current directory, the state of the system) to generate more relevant commands.
* **Domain-Specific Knowledge:** The command mapping needs to be tailored to the specific DevOps environment and tools being used.
* **Idempotency:** Consider whether the generated commands are idempotent (i.e., can be executed multiple times without changing the result).
* **Error Handling and Logging:** Robust error handling and logging are essential for debugging and monitoring the system.
* **Configuration:** The command mapping and other settings should be configurable.
* **Authentication and Authorization:** Ensure that the user is authenticated and authorized to execute the generated commands.
* **Testing:** Thoroughly test the program with a wide range of inputs to ensure its accuracy and security.
* **Infrastructure as Code (IaC):** For more complex tasks, consider using IaC tools like Terraform or Ansible to manage infrastructure in a declarative way. The natural language interface could then generate configuration files for these tools.
* **Agent-Based Architecture:** A real system might involve an agent running on the target machine to execute commands securely.
* **User Interface:** A more user-friendly interface (e.g., a web interface or a chatbot) would be beneficial.
* **Shell Injection Prevention:** Never directly use the extracted parameters in the `subprocess.run` shell=True command. This opens a huge security hole for shell injection. If you *must* use `shell=True`, then carefully sanitize the input. A much better approach is to use `shell=False` and pass the command and parameters as a list. This prevents shell injection. However, it requires knowing the *exact* command-line syntax of the underlying commands.
This improved example provides a much better starting point for building a more robust and practical natural language to Bash command generator. Remember to prioritize security and thorough testing in any real-world implementation.
👁️ Viewed: 4
Comments