Key Concepts¶
Understanding these core concepts will help you use fscm effectively.
Change Tracking¶
Every operation in fscm is tracked. When you call file(), run(), or any other function that modifies the system, a Change object is recorded.
import fscm
from fscm import file, run
file("/etc/myapp.conf", "setting=value\n")
run("systemctl restart myapp", sudo=True)
# View all changes
for change in fscm.CHANGELIST:
print(change)
Output:
Change Types¶
| Change Type | Description |
|---|---|
FileAdd |
New file created |
FileModify |
Existing file modified |
FileRm |
File removed |
DirAdd |
Directory created |
CmdRun |
Command executed |
PkgAdd |
Package installed |
ChmodModify |
Permissions changed |
ChownModify |
Ownership changed |
SymlinkAdd |
Symlink created |
Why Track Changes?¶
- Audit trail — Know exactly what was modified
- Dry-run mode — Preview changes before applying
- Idempotency checking — Detect if changes are needed
- Debugging — Understand what your script did
Dry-Run Mode¶
Dry-run mode simulates all operations without making actual changes.
import fscm
# Enable dry-run
fscm.settings.dry_run = True
# These won't actually happen
fscm.s.pkgs_install("nginx") # Won't install
fscm.file("/etc/config", "x") # Won't write
fscm.run("rm -rf /") # Definitely won't run!
# But changes are still tracked
print(fscm.CHANGELIST) # Shows what WOULD have happened
Best Practice
Always run with --dry-run first, especially on production systems.
System Detection¶
fscm automatically detects your operating system and uses the appropriate package manager and system commands.
import fscm
# Detect the current system
system = fscm.detect_system()
print(type(system)) # Debian, Arch, or MacOS
# The global 's' object is pre-configured for your system
fscm.s.pkgs_install("nginx") # Uses apt, pacman, or brew
Supported Systems¶
| System | Class | Package Manager |
|---|---|---|
| Debian/Ubuntu | Debian |
apt-get |
| Arch Linux | Arch |
pacman |
| macOS | MacOS |
Homebrew |
Manual System Selection¶
The Settings Object¶
Global configuration is managed through fscm.settings:
import fscm
# Dry-run mode
fscm.settings.dry_run = True
# Sudo password (for automated sudo)
fscm.settings.sudo_password = "secret"
# Disable colored output
fscm.settings.stream_output = False
# Backup settings
fscm.settings.backup_dir = "/var/backups/fscm"
fscm.settings.backup_threshold = 1024 * 1024 # 1MB max
Key Settings¶
| Setting | Type | Description |
|---|---|---|
dry_run |
bool | Simulate operations |
sudo_password |
str | Password for sudo |
stream_output |
bool | Show command output |
backup_dir |
Path | Where to store backups |
backup_threshold |
int | Max file size to backup |
container_cmd |
str | Docker or podman |
Idempotency¶
fscm operations are designed to be idempotent — running them multiple times produces the same result.
import fscm
# Running twice has no additional effect
fscm.file("/etc/config", "content")
fscm.file("/etc/config", "content") # No change, file already matches
# Package installation is idempotent
fscm.s.pkgs_install("nginx") # Installs nginx
fscm.s.pkgs_install("nginx") # No-op, already installed
How Idempotency Works¶
| Operation | Check Before Acting |
|---|---|
file() |
Compares content hash |
mkdir() |
Checks if dir exists |
pkgs_install() |
Checks if installed |
chmod() |
Compares current mode |
chown() |
Compares current owner |
File Backups¶
Before modifying files, fscm can create backups:
import fscm
# Configure backups
fscm.settings.backup_dir = "/var/backups/fscm"
fscm.settings.backup_threshold = 1024 * 1024 # Skip files > 1MB
# This will backup /etc/nginx/nginx.conf before modifying
fscm.file("/etc/nginx/nginx.conf", new_content)
Backups are stored with timestamps:
The run() Function¶
The run() function executes shell commands with many options:
import fscm
# Basic command
result = fscm.run("ls -la")
# With sudo
fscm.run("systemctl restart nginx", sudo=True)
# Capture output
result = fscm.run("cat /etc/hostname")
print(result.stdout)
# Check success
result = fscm.run("some-command", check=False)
if result.ok:
print("Success!")
# Quiet mode (no output)
fscm.run("apt-get update", quiet=True, sudo=True)
RunReturn Object¶
result = fscm.run("command")
result.ok # True if returncode == 0
result.returncode # Exit code
result.stdout # Standard output
result.stderr # Standard error
result.assert_ok() # Raise if failed
Next Steps¶
- File Operations — Deep dive into file management
- Command Execution — Advanced run() usage
- Remote Execution — Run on remote hosts