{"id":49868201,"url":"https://github.com/open-technology-foundation/locks","last_synced_at":"2026-05-15T04:03:02.088Z","repository":{"id":320307339,"uuid":"1081568292","full_name":"Open-Technology-Foundation/locks","owner":"Open-Technology-Foundation","description":"Robust, production-ready file-based locking utility using flock(1) for safe concurrent script execution, with stale lock detection and flexible waiting modes.","archived":false,"fork":false,"pushed_at":"2025-10-23T02:45:00.000Z","size":38,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-10-23T04:26:08.436Z","etag":null,"topics":["bash-script","flock","locking"],"latest_commit_sha":null,"homepage":"https://yatti.id/","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Open-Technology-Foundation.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-10-23T01:00:59.000Z","updated_at":"2025-10-23T02:45:03.000Z","dependencies_parsed_at":"2025-10-23T04:26:23.774Z","dependency_job_id":"84a6f389-bce1-4196-af4c-8977d0144441","html_url":"https://github.com/Open-Technology-Foundation/locks","commit_stats":null,"previous_names":["open-technology-foundation/locks"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/Open-Technology-Foundation/locks","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Open-Technology-Foundation%2Flocks","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Open-Technology-Foundation%2Flocks/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Open-Technology-Foundation%2Flocks/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Open-Technology-Foundation%2Flocks/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Open-Technology-Foundation","download_url":"https://codeload.github.com/Open-Technology-Foundation/locks/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Open-Technology-Foundation%2Flocks/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33053144,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-13T13:14:54.681Z","status":"online","status_checked_at":"2026-05-15T02:00:06.351Z","response_time":103,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bash-script","flock","locking"],"created_at":"2026-05-15T04:02:51.429Z","updated_at":"2026-05-15T04:03:02.082Z","avatar_url":"https://github.com/Open-Technology-Foundation.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# shlock - File-based Locking System\n\nA robust, production-ready file-based locking utility using `flock(1)` for safe concurrent script execution with stale lock detection and flexible waiting modes.\n\n## Table of Contents\n\n- [Features](#features)\n- [Installation](#installation)\n- [Usage](#usage)\n- [Options](#options)\n- [Exit Codes](#exit-codes)\n- [Examples](#examples)\n- [How It Works](#how-it-works)\n- [Use Cases](#use-cases)\n- [Testing](#testing)\n- [Troubleshooting](#troubleshooting)\n- [Best Practices](#best-practices)\n\n## Features\n\n- **Exclusive Locking**: Prevents multiple instances of the same operation from running simultaneously\n- **Stale Lock Detection**: Automatically removes locks left behind by crashed processes\n- **Flexible Waiting Modes**:\n  - Non-blocking (default): Fail immediately if lock is held\n  - Blocking: Wait indefinitely for lock to become available\n  - Timeout: Wait up to a specified number of seconds\n- **PID Tracking**: Tracks which process holds each lock\n- **Clean Exit Handling**: Automatic lock cleanup on normal exit or signal termination\n- **Safe for Automation**: Ideal for cron jobs, systemd services, and CI/CD pipelines\n- **Comprehensive Error Messages**: Clear, actionable error reporting\n- **Battle-tested**: 103 comprehensive test cases\n\n## Installation\n\n### Complete Installation (Recommended)\n\nInstall the script, manpage, and bash completion using either the Makefile or installation script.\n\n#### Using Makefile\n\n```bash\n# Install to /usr/local (default) - may require sudo\nmake install\n\n# Install to /usr - requires sudo\nsudo make PREFIX=/usr install\n\n# Install to user directory (no sudo needed)\nmake PREFIX=~/.local install\n\n# Uninstall\nmake uninstall\n```\n\n#### Using install.sh Script\n\n```bash\n# Install to /usr/local (default) - may require sudo\n./install.sh install\n\n# Install to /usr - requires sudo\nsudo ./install.sh --prefix /usr install\n\n# Install to user directory (no sudo needed)\n./install.sh --prefix ~/.local install\n\n# Skip confirmation prompts\n./install.sh -y install\n\n# Uninstall\n./install.sh uninstall\n```\n\n### Partial Installation\n\nInstall only specific components:\n\n#### Install Script Only\n\n```bash\n# Using Makefile\nmake install-script\n\n# Using install.sh\n./install.sh install-script\n```\n\n#### Install Manpage Only\n\n```bash\n# Using Makefile\nmake install-man\n\n# Using install.sh\n./install.sh install-man\n```\n\n#### Install Bash Completion Only\n\n```bash\n# Using Makefile\nmake install-completion\n\n# Using install.sh\n./install.sh install-completion\n```\n\n### Manual Installation\n\nIf you prefer manual installation:\n\n```bash\n# Copy script\nsudo cp shlock /usr/local/bin/\nsudo chmod +x /usr/local/bin/shlock\n\n# Build and install manpage (requires pandoc)\npandoc --standalone --to man -o shlock.1 shlock.1.md\nsudo cp shlock.1 /usr/local/share/man/man1/\nsudo mandb -q\n\n# Install bash completion\nsudo cp shlock.bash_completion /usr/share/bash-completion/completions/shlock\n```\n\n### Direct Usage (No Installation)\n\nUse directly from the repository without installing:\n\n```bash\n/ai/scripts/lib/shlock/shlock [OPTIONS] [LOCKNAME] -- COMMAND [ARGS...]\n```\n\n### Installation Requirements\n\n**Script requirements:**\n- Bash 5.0 or later\n- `flock` utility (usually from `util-linux` package)\n- `/run/lock` directory (standard on most Linux distributions)\n\n**Manpage build requirements** (optional, only needed for `make install-man`):\n- **pandoc** - Document converter\n\nInstall pandoc:\n```bash\n# Debian/Ubuntu\nsudo apt install pandoc\n\n# Fedora/RHEL\nsudo dnf install pandoc\n\n# macOS\nbrew install pandoc\n```\n\n### Bash Completion\n\nBash completion is automatically installed with `make install` or `./install.sh install`. It provides intelligent tab-completion for:\n\n- **Options**: `-m`, `-w`, `-t`, `--max-age`, `--wait`, `--timeout`, `--help`, `--version`\n- **Lock names**: Existing locks from `/run/lock/*.lock`\n- **Commands**: After `--`, completes available commands and files\n\n**Manual activation** (if not using system-wide installation):\n\n```bash\n# Source completion for current shell\nsource shlock.bash_completion\n\n# Or add to ~/.bashrc for permanent activation\necho 'source /path/to/shlock.bash_completion' \u003e\u003e ~/.bashrc\n```\n\n**Usage examples:**\n```bash\nshlock --\u003cTAB\u003e         # Shows: --help --max-age --timeout --version --wait\nshlock -m \u003cTAB\u003e        # Suggests hours values\nshlock -t \u003cTAB\u003e        # Suggests seconds values\nshlock backup\u003cTAB\u003e     # Shows existing lock names starting with 'backup'\nshlock mylock -- \u003cTAB\u003e # Completes available commands\n```\n\n### Custom Prefix Configuration\n\nIf installing to a custom prefix (e.g., `~/.local`), add to your `~/.bashrc` or `~/.profile`:\n\n```bash\nexport PATH=\"$HOME/.local/bin:$PATH\"\nexport MANPATH=\"$HOME/.local/share/man:$MANPATH\"\n\n# Bash completion directory (if needed)\nexport BASH_COMPLETION_USER_DIR=\"$HOME/.local/share/bash-completion\"\n```\n\nAfter installation to a custom prefix, restart your shell or run:\n```bash\nsource ~/.bashrc\n```\n\n### Renaming the Script\n\nYou can rename the script to any name you prefer without affecting functionality. This is useful to avoid name conflicts with other programs:\n\n```bash\n# Rename to avoid conflicts\nmv shlock sherlock\nchmod +x sherlock\n\n# Use with new name\nsherlock backup -- /usr/local/bin/backup.sh\n```\n\nThe script name is not referenced internally, so renaming has no effect on its operation.\n\n## Usage\n\n```bash\nshlock [OPTIONS] [LOCKNAME] -- COMMAND [ARGS...]\n```\n\n### Arguments\n\n- **LOCKNAME**: Unique identifier for the lock (e.g., `backup`, `deployment`, `sync`)\n  - **Optional**: If omitted, auto-generated from basename of COMMAND\n  - Example: `shlock -- /usr/local/bin/backup.sh` uses lockname \"backup.sh\"\n- **COMMAND**: Command to execute while holding the lock\n- **ARGS**: Optional arguments passed to COMMAND\n\n**Important**: The `--` separator is required to separate options from the command.\n\n## Options\n\n| Option | Argument | Description |\n|--------|----------|-------------|\n| `--max-age` | HOURS | Maximum lock age before considered stale (default: 24) |\n| `--wait` | - | Wait indefinitely for lock to become available |\n| `--timeout` | SECONDS | Maximum time to wait for lock (implies `--wait`) |\n| `-h, --help` | - | Display help message |\n| `-V, --version` | - | Display version information |\n\n## Exit Codes\n\n| Code | Meaning |\n|------|---------|\n| 0 | Command executed successfully |\n| 1 | Lock acquisition failed (held by another process or timeout) |\n| 2 | Invalid arguments |\n| 3 | Command failed |\n\n## Examples\n\n### Basic Usage (Non-blocking)\n\nFail immediately if lock is already held:\n\n```bash\n# Explicit lock name\nshlock backup -- /usr/local/bin/backup.sh\n\n# Auto-generated lock name (from command basename)\nshlock -- /usr/local/bin/backup.sh\n\n# Lock with arguments\nshlock sync -- rsync -av /src /dest\n\n# Lock with custom stale threshold\nshlock --max-age 12 critical -- /path/to/critical.sh\n```\n\n### Blocking Mode (Wait Indefinitely)\n\nWait until the lock becomes available:\n\n```bash\n# Wait for deployment lock\nshlock --wait deployment -- ./deploy.sh production\n\n# Wait with custom stale threshold\nshlock --max-age 6 --wait database-backup -- /usr/local/bin/db-backup.sh\n```\n\n### Timeout Mode\n\nWait up to a specified time:\n\n```bash\n# Wait up to 30 seconds\nshlock --timeout 30 sync -- rsync -av /src /dest\n\n# Wait up to 5 minutes (300 seconds)\nshlock --timeout 300 report -- /usr/local/bin/generate-report.sh\n\n# Critical task with short timeout\nshlock --timeout 10 healthcheck -- curl -f http://localhost/health\n```\n\n### Cron Job Usage\n\nPrevent overlapping executions:\n\n```bash\n# In crontab with explicit lock name\n*/5 * * * * /usr/local/bin/shlock backup -- /usr/local/bin/backup.sh 2\u003e\u00261 | logger -t backup\n\n# Using auto-generated lock name\n*/5 * * * * /usr/local/bin/shlock -- /usr/local/bin/backup.sh 2\u003e\u00261 | logger -t backup\n\n# With timeout for long-running tasks\n0 2 * * * /usr/local/bin/shlock --timeout 3600 nightly-job -- /usr/local/bin/nightly.sh\n```\n\n### Systemd Service\n\n```bash\n# In your script or ExecStart\nExecStart=/usr/local/bin/shlock --wait service-name -- /usr/local/bin/your-service\n```\n\n### CI/CD Pipeline\n\n```bash\n#!/bin/bash\n# Ensure only one deployment runs at a time\n\nif ! shlock --timeout 60 deploy-prod -- ./deploy.sh production; then\n    echo \"Deployment already in progress or timed out\"\n    exit 1\nfi\n```\n\n### Error Handling\n\n```bash\n#!/bin/bash\n\nif shlock database-maintenance -- /usr/local/bin/maintenance.sh; then\n    echo \"Maintenance completed successfully\"\nelse\n    exit_code=$?\n    case $exit_code in\n        1)\n            echo \"Lock is held by another process\"\n            ;;\n        2)\n            echo \"Invalid arguments\"\n            ;;\n        3)\n            echo \"Maintenance script failed\"\n            ;;\n    esac\n    exit $exit_code\nfi\n```\n\n## How It Works\n\n### Locking Mechanism\n\n1. **LOCKNAME Resolution**: If LOCKNAME is omitted, derives it from the basename of COMMAND\n2. **Lock Directory Determination**: Automatically selects lock directory:\n   - Tries `/run/lock` (standard tmpfs location)\n   - Falls back to `/var/lock` if `/run/lock` unavailable\n   - Falls back to `/tmp/locks` (created if needed)\n   - Fails if no directory is writable\n3. **Lock File Creation**: Creates a lock file at `\u003cLOCK_DIR\u003e/\u003cLOCKNAME\u003e.lock`\n4. **Stale Lock Check**: If lock file exists, checks if it's older than `--max-age` hours\n5. **Process Validation**: Verifies if the process that created the lock is still running\n6. **Lock Acquisition**: Uses `flock(1)` for atomic, kernel-level locking\n7. **PID Tracking**: Writes the script's PID to `\u003cLOCK_DIR\u003e/\u003cLOCKNAME\u003e.pid`\n8. **Command Execution**: Runs the specified command while holding the lock\n9. **Cleanup**: Automatically removes PID file on exit; lock file persists for reuse\n\n### File Locations\n\nLock files are stored in the first writable directory from this list:\n\n1. **`/run/lock/`** (preferred) - tmpfs filesystem, cleared on reboot\n2. **`/var/lock/`** (fallback) - persistent across reboots on most systems\n3. **`/tmp/locks/`** (last resort) - created automatically if needed, cleared on reboot\n\nFile patterns:\n- **Lock files**: `\u003cLOCK_DIR\u003e/\u003cLOCKNAME\u003e.lock`\n- **PID files**: `\u003cLOCK_DIR\u003e/\u003cLOCKNAME\u003e.pid`\n\n### Stale Lock Detection\n\nA lock is considered stale when:\n1. The lock file is older than `--max-age` hours (default: 24)\n2. AND the process listed in the PID file is not running\n\nIf a lock is stale but the process is still running, the lock acquisition fails with a warning that the process has been running for an unusually long time.\n\n### Waiting Modes\n\n**Non-blocking (default)**:\n- Attempts to acquire lock once\n- Fails immediately if lock is held\n- Best for: Cron jobs where you want to skip if already running\n\n**Blocking (`--wait`)**:\n- Waits indefinitely for lock to become available\n- Acquires lock as soon as it's released\n- Best for: Sequential tasks that must eventually run\n\n**Timeout (`--timeout SECONDS`)**:\n- Waits up to specified seconds for lock\n- Fails with exit code 1 if timeout expires\n- Best for: Tasks with time constraints\n\n## Use Cases\n\n### 1. Prevent Overlapping Cron Jobs\n\n```bash\n# In crontab - runs every 5 minutes but skips if previous run is still active\n*/5 * * * * shlock sync -- /usr/local/bin/sync-data.sh\n\n# Or use auto-generated lock name\n*/5 * * * * shlock -- /usr/local/bin/sync-data.sh\n```\n\n### 2. Serialize Database Operations\n\n```bash\n# Multiple scripts accessing the same database\nshlock --wait database -- /usr/local/bin/db-operation-1.sh\nshlock --wait database -- /usr/local/bin/db-operation-2.sh\n```\n\n### 3. Safe Deployment Pipeline\n\n```bash\n# Ensure only one deployment runs at a time\nshlock --timeout 300 deployment -- ./deploy.sh \"$ENVIRONMENT\"\n```\n\n### 4. Resource-Intensive Tasks\n\n```bash\n# Prevent multiple instances of CPU/IO-heavy operations\nshlock backup -- /usr/local/bin/full-backup.sh\nshlock indexing -- /usr/local/bin/rebuild-search-index.sh\n```\n\n### 5. Graceful Service Restarts\n\n```bash\n# Prevent multiple restart attempts\nshlock --timeout 30 service-restart -- systemctl restart myservice\n```\n\n## Testing\n\nThe utility includes a comprehensive test suite with 103 test cases covering all functionality.\n\n### Running Tests\n\n```bash\n# Run all tests\ncd /ai/scripts/lib/shlock/tests\n./run_tests.sh\n\n# Run specific test file\n./test_basic.sh\n./test_wait_timeout.sh\n```\n\n### Test Coverage\n\n- **test_basic.sh** (15 tests): Basic functionality, argument handling, exit codes\n- **test_concurrent.sh** (13 tests): Concurrent lock acquisition, race conditions\n- **test_edge_cases.sh** (24 tests): Edge cases, stress tests, special characters\n- **test_errors.sh** (27 tests): Error handling, invalid inputs, signal handling\n- **test_stale_locks.sh** (11 tests): Stale lock detection, max-age thresholds\n- **test_wait_timeout.sh** (13 tests): Blocking mode, timeout behavior, queuing\n\n## Troubleshooting\n\n### Lock Won't Release\n\n**Symptom**: Lock appears held even though no process is running\n\n**Solutions**:\n```bash\n# Check for lock files\nls -la /run/lock/YOUR_LOCKNAME.*\n\n# Check which process holds the lock\ncat /run/lock/YOUR_LOCKNAME.pid\nps -p $(cat /run/lock/YOUR_LOCKNAME.pid)\n\n# Force remove stale lock (use with caution)\nrm -f /run/lock/YOUR_LOCKNAME.lock /run/lock/YOUR_LOCKNAME.pid\n```\n\n### Permission Denied\n\n**Symptom**: Cannot create lock files\n\n**Solutions**:\n```bash\n# Check /run/lock permissions\nls -ld /run/lock\n\n# Ensure your user can write to /run/lock\n# Typically this requires being in the appropriate group or running as root\n```\n\n### Timeout Not Working\n\n**Symptom**: `--timeout` flag not recognized or failing\n\n**Check**:\n1. Verify `flock` supports `-w` option: `flock --help | grep -e '-w'`\n2. Update util-linux if needed: `apt-get update \u0026\u0026 apt-get install util-linux`\n3. Ensure timeout value is numeric and positive\n\n### Lock Always Considered Stale\n\n**Symptom**: Lock is removed even when process is running\n\n**Check**:\n```bash\n# Verify timestamp on lock file\nstat /run/lock/YOUR_LOCKNAME.lock\n\n# Check if system time is correct\ndate\n```\n\n## Best Practices\n\n### 1. Choose Meaningful Lock Names\n\n```bash\n# Good - explicit lock names\nshlock database-backup -- ...\nshlock customer-data-sync -- ...\nshlock nightly-reports -- ...\n\n# Also good - auto-generated from descriptive script names\nshlock -- /usr/local/bin/database-backup.sh\nshlock -- /usr/local/bin/customer-data-sync.sh\n\n# Avoid\nshlock lock1 -- ...\nshlock temp -- ...\n```\n\n### 2. Set Appropriate max-age Values\n\n```bash\n# Short-running tasks (\u003c 1 hour)\nshlock --max-age 2 quick-sync -- ...\n\n# Medium tasks (few hours)\nshlock --max-age 12 backup -- ...\n\n# Long-running tasks (overnight)\nshlock --max-age 48 monthly-report -- ...\n```\n\n### 3. Use Timeout for Critical Paths\n\n```bash\n# Don't let deployments wait forever\nshlock --timeout 300 deployment -- ./deploy.sh\n\n# Quick healthchecks should timeout fast\nshlock --timeout 5 healthcheck -- ./check-health.sh\n```\n\n### 4. Handle Exit Codes Properly\n\n```bash\nif ! shlock backup -- /usr/local/bin/backup.sh; then\n    # Alert, log, or take corrective action\n    echo \"Backup failed or locked\" | mail -s \"Backup Alert\" admin@example.com\nfi\n```\n\n### 5. Log Lock Events\n\n```bash\n# In cron\n* * * * * shlock task -- /path/to/script.sh 2\u003e\u00261 | logger -t task-lock\n\n# In scripts\nshlock task -- /path/to/script.sh 2\u003e\u00261 | tee -a /var/log/task.log\n```\n\n### 6. Combine with Monitoring\n\n```bash\n#!/bin/bash\n# Check if lock is held too long\n\nLOCK_FILE=\"/run/lock/backup.lock\"\nMAX_AGE_SECONDS=7200  # 2 hours\n\nif [[ -f \"$LOCK_FILE\" ]]; then\n    AGE=$(($(date +%s) - $(stat -c %Y \"$LOCK_FILE\")))\n    if ((AGE \u003e MAX_AGE_SECONDS)); then\n        echo \"Warning: backup lock held for ${AGE} seconds\" | \\\n            mail -s \"Lock Alert\" admin@example.com\n    fi\nfi\n```\n\n### 7. Document Lock Dependencies\n\n```bash\n# README or comment in script\n# This script uses locks:\n# - \"database-backup\" - Exclusive access to database during backup\n# - \"file-sync\" - Prevents concurrent rsync operations\n#\n# Dependencies:\n# - database-backup must complete before file-sync can run\n```\n\n## Advanced Usage\n\n### Nested Operations (Different Locks)\n\n```bash\n#!/bin/bash\n# Outer operation\nshlock operation-a -- bash -c '\n    echo \"Running operation A\"\n\n    # Inner operation with different lock\n    shlock operation-b -- echo \"Running operation B\"\n'\n```\n\n### Conditional Locking\n\n```bash\n#!/bin/bash\n\nif [[ \"$FORCE\" == \"yes\" ]]; then\n    # Skip lock for forced execution\n    /usr/local/bin/task.sh\nelse\n    # Normal locked execution\n    shlock task -- /usr/local/bin/task.sh\nfi\n```\n\n### Integration with systemd\n\n```ini\n[Unit]\nDescription=My Locked Service\nAfter=network.target\n\n[Service]\nType=oneshot\nExecStart=/usr/local/bin/shlock --wait my-service -- /usr/local/bin/my-service.sh\nStandardOutput=journal\nStandardError=journal\n\n[Install]\nWantedBy=multi-user.target\n```\n\n## Performance Considerations\n\n- **Lock file creation**: Negligible overhead (\u003c 1ms)\n- **Lock acquisition**: Atomic kernel operation (\u003c 1ms)\n- **Stale lock check**: Single file stat + process check (\u003c 10ms)\n- **Lock release**: Automatic on process exit\n\nThe utility adds minimal overhead to command execution, making it suitable for frequent operations and time-sensitive tasks.\n\n## Security Considerations\n\n1. **File Permissions**: Lock files inherit permissions from `/run/lock` (typically world-writable with sticky bit)\n2. **PID Spoofing**: The utility validates process existence but doesn't verify process identity\n3. **Race Conditions**: `flock` provides atomic locking, preventing race conditions\n4. **Symlink Attacks**: Lock files are created with `\u003e` redirection, following symlinks\n\nFor security-critical applications, consider:\n- Running with appropriate user permissions\n- Using dedicated lock directories with restricted permissions\n- Implementing additional process validation\n\n## FAQ\n\n**Q: What happens if the system crashes while holding a lock?**\nA: The lock file persists but becomes stale. On next acquisition attempt, it will be removed if older than `--max-age` and the PID is not running.\n\n**Q: Can I use the same lock name from different scripts?**\nA: Yes, that's the intended use. The same lock name ensures mutual exclusion across all scripts using it.\n\n**Q: What if `/run/lock` doesn't exist?**\nA: shlock automatically falls back through multiple directories: `/run/lock` → `/var/lock` → `/tmp/locks` (created if needed). If none are writable, the script fails with an error message.\n\n**Q: Is it safe to use in containers?**\nA: Yes, but note that locks are container-scoped. Different containers don't share locks unless they share the same `/run/lock` volume.\n\n**Q: Can I use this with non-Bash scripts?**\nA: Yes, you can lock any executable: `shlock task -- python3 script.py` or `shlock task -- /usr/bin/my-binary`\n\n**Q: How many locks can I have?**\nA: Practically unlimited. Each lock is just two small files in `/run/lock`.\n\n## Contributing\n\nContributions are welcome! Please ensure:\n- All tests pass: `./tests/run_tests.sh`\n- Shellcheck compliance: `shellcheck shlock`\n- Documentation updates for new features\n\n## License\n\nThis utility is part of the Okusi Group bash scripting standard library.\n\n## See Also\n\n- `flock(1)` - Linux manual page\n- `fcntl(2)` - POSIX file locking\n- Bash Coding Standard: `/ai/scripts/Okusi/bash-coding-standard/`\n\n---\n\n**Version**: 1.0.0\n**Last Updated**: 2025-10-23\n**Maintainer**: Gary Dean (Biksu Okusi)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopen-technology-foundation%2Flocks","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fopen-technology-foundation%2Flocks","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopen-technology-foundation%2Flocks/lists"}