Created
January 30, 2026 05:06
-
-
Save DorianZheng/29bdc1a12e6f141628b19265b13a0f36 to your computer and use it in GitHub Desktop.
Fuse in BoxLite demo
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 # Shebang for direct execution | |
| import asyncio # Async runtime for SimpleBox | |
| import boxlite # BoxLite Python SDK | |
| import textwrap # Embed the guest-side FUSE script as a string | |
| # Minimal FUSE filesystem served inside the box (as a multi-line string) | |
| FUSE_SCRIPT = textwrap.dedent(r""" | |
| #!/usr/bin/env python3 # Guest-side shebang | |
| import os, sys, time, stat # Stdlib imports inside guest | |
| from mfusepy import FUSE, Operations # FUSE bindings inside guest | |
| class Hello(Operations): # Minimal FUSE filesystem implementation | |
| use_ns = True # Use nanosecond timestamps to avoid utimens float deprecation | |
| def readdir(self, path, fh): # List directory entries | |
| return [".", "..", "hello.txt"] # Root contains one file | |
| def getattr(self, path, fh=None): # Return metadata for paths | |
| now = time.time() # Current timestamp for attributes | |
| if path == "/": # Root directory attributes | |
| return dict(st_mode=stat.S_IFDIR | 0o755, st_nlink=2, | |
| st_ctime=now, st_mtime=now, st_atime=now) # Dir attrs | |
| return dict(st_mode=stat.S_IFREG | 0o444, st_nlink=1, st_size=12, | |
| st_ctime=now, st_mtime=now, st_atime=now) # File attrs | |
| def read(self, path, size, offset, fh): # Provide file contents | |
| return b"hello world\n"[offset:offset+size] # Slice static bytes | |
| if __name__ == "__main__": # Guest entrypoint | |
| mountpoint = sys.argv[1] # Mount target from argv | |
| os.makedirs(mountpoint, exist_ok=True) # Ensure mount dir exists | |
| os.environ.setdefault("FUSE_LIBRARY_PATH", "/usr/lib/libfuse3.so.4") # Point to libfuse3 | |
| FUSE(Hello(), mountpoint, foreground=True) # Run FUSE in foreground | |
| """) # End of guest script string | |
| async def main(): # Host-side async entrypoint | |
| async with boxlite.SimpleBox(image="alpine:latest") as box: # Start Alpine box | |
| async def run(label, *cmd): # Helper: run a command and print outputs | |
| res = await box.exec(*cmd) # Execute inside the box | |
| print(f"[{label}] exit={res.exit_code}") # Show exit code | |
| if res.stdout: # If stdout exists | |
| print(f"[{label}] stdout:\n{res.stdout.rstrip()}\n") # Print stdout | |
| if res.stderr: # If stderr exists | |
| print(f"[{label}] stderr:\n{res.stderr.rstrip()}\n") # Print stderr | |
| return res # Return ExecResult | |
| await run("apk", "apk", "add", "--no-cache", # Install FUSE and Python | |
| "fuse", "fuse3", "fuse3-libs", "python3", "py3-pip") # Packages list | |
| await run("mknod", "sh", "-c", "test -e /dev/fuse || mknod /dev/fuse c 10 229") # Ensure /dev/fuse | |
| await run("pip", "pip3", "install", "--no-cache-dir", # Install mfusepy | |
| "--break-system-packages", "mfusepy==3.1.0") # Version pin | |
| await run("write", "sh", "-c", f"cat > /tmp/hello_fuse.py <<'PY'\n{FUSE_SCRIPT}\nPY") # Write guest script | |
| await run("chmod", "chmod", "+x", "/tmp/hello_fuse.py") # Make script executable | |
| await run("mkdir", "mkdir", "-p", "/tmp/mnt") # Create mountpoint | |
| pid = (await run("start", "sh", "-c", # Launch FUSE server in background | |
| "python3 /tmp/hello_fuse.py /tmp/mnt >/tmp/fuse.log 2>&1 & echo $!" | |
| )).stdout.strip() # Capture PID | |
| await run("cat", "cat", "/tmp/mnt/hello.txt") # Read from FUSE FS | |
| await run("fusermount", "fusermount3", "-u", "/tmp/mnt") # Unmount | |
| await run("kill", "kill", pid) # Stop server process | |
| await run("log", "cat", "/tmp/fuse.log") # Show server log | |
| print(f"[info] FUSE server PID was {pid}") # Final info line | |
| if __name__ == "__main__": # Script entrypoint | |
| asyncio.run(main()) # Run async main |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment