{"id":18151301,"url":"https://github.com/msantos/pseudocron","last_synced_at":"2026-02-24T01:10:34.103Z","repository":{"id":136621479,"uuid":"119273519","full_name":"msantos/pseudocron","owner":"msantos","description":"sleep(1) using a cron expression","archived":false,"fork":false,"pushed_at":"2025-02-12T12:43:56.000Z","size":51,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-02-12T13:55:33.260Z","etag":null,"topics":["capsicum","cron","pledge","seccomp"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/msantos.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}},"created_at":"2018-01-28T16:03:20.000Z","updated_at":"2025-02-12T12:44:00.000Z","dependencies_parsed_at":null,"dependency_job_id":"2ab72db8-27b0-4bc4-87ed-a2789e007e9b","html_url":"https://github.com/msantos/pseudocron","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/msantos%2Fpseudocron","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/msantos%2Fpseudocron/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/msantos%2Fpseudocron/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/msantos%2Fpseudocron/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/msantos","download_url":"https://codeload.github.com/msantos/pseudocron/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":238602655,"owners_count":19499444,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["capsicum","cron","pledge","seccomp"],"created_at":"2024-11-02T01:07:17.414Z","updated_at":"2025-10-28T05:30:37.880Z","avatar_url":"https://github.com/msantos.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# SYNOPSIS\n\npseudocron [-n|-p|-v] *crontab expression*\n\n# DESCRIPTION\n\npseudocron: sleep(1) using a cron expression\n\nAlso see [runcron](https://github.com/msantos/runcron).\n\ncron expressions are parsed using\n[ccronexpr](https://github.com/staticlibs/ccronexpr).\n\n* simple\n\n  pseudocron is sleep(1) that accepts a crontab(5) expression for the\n  duration and then exits. That's all it does.\n\n  Use a supervisor like [daemontools](https://cr.yp.to/daemontools.html)\n  to run the job.\n\n* safe\n\n  No setuid binaries or processes running as root.\n\n  pseudocron operations are restricted. It cannot open files\n  or sockets or signal processes. The only ways pseudocron can\n  interact with other processes is via stdin/stdout/stderr and\n  the process exit value.\n\n* container friendly\n\n  pseudocron runs as a normal user without any special privileges.\n  It does not need to modify the filesystem. pseudocron is meant to\n  run in an automated environment without user intervention.\n\n  Since processes run sequentially and synchronously, jobs won't pile\n  up if the run time of the task exceeds the time spec increment unless\n  specifically requested to run in the background.\n\n  pseudocron does not modify the application environment or interfere\n  with stdio.\n\nThe standard crontab(5) expressions are supported. The seconds field\nis optional:\n\n```\n\t\t\tfield          allowed values\n\t\t\t-----          --------------\n\t\t\tsecond         0-59 (optional)\n\t\t\tminute         0-59\n\t\t\thour           0-23\n\t\t\tday of month   1-31\n\t\t\tmonth          1-12 (or names, see below)\n\t\t\tday of week    0-7 (0 or 7 is Sun, or use names)\n```\n\ncrontab(5) aliases also work:\n\n```\n\t\t\tstring         meaning\n\t\t\t------         -------\n\t\t\t@reboot        Run once, at startup (see below).\n\t\t\t@yearly        Run once a year, \"0 0 1 1 *\".\n\t\t\t@annually      (same as @yearly)\n\t\t\t@monthly       Run once a month, \"0 0 1 * *\".\n\t\t\t@weekly        Run once a week, \"0 0 * * 0\".\n\t\t\t@daily         Run once a day, \"0 0 * * *\".\n\t\t\t@midnight      (same as @daily)\n\t\t\t@hourly        Run once an hour, \"0 * * * *\".\n\t\t\t@never         Never run (sleep forever)\n```\n\n## @reboot\n\nUnlike *crontab*(5), `pseudocron` will run the `@reboot` alias\nimmediately.\n\nThe behaviour can be mimicked by setting the `PSEUDOCRON_REBOOT`\nenvironment variable. If the variable is unset, `@reboot` is equivalent to\n`* * * * * *`.\n\nIf set to any value, `@reboot` is equivalent to `@never`.\n\n```shell\n#!/bin/sh\n\nwhile :; do\n    # runs in the next second\n    pseudocron \"@reboot\"\n    echo test\n    export PSEUDOCRON_REBOOT=1\n    # equivalent to sleep infinity\ndone\n```\n\n# EXAMPLES\n\n```\n    # parse only the crontab expression\n    # every 15 minutes (5 fields)\n    pseudocron -n \"*/15 * * * *\"\n\n    # parse only the crontab expression and view the calculated times\n    # every 15 seconds (6 fields)\n    pseudocron -nvv \"*/15 * * * * *\"\n```\n\nWriting a batch job:\n\n```\n    #!/bin/sh\n    \n    set -e\n    \n    # Run daily at 8:15am\n    pseudocron \"15 8 * * *\"\n    echo Running job\n```\n\n# OPTIONS\n\n-n, --dryrun\n: Do not sleep. Can be used to verify the crontab expression.\n\n-p, --print\n: Output the number of seconds to the next crontab time specification.\n\n-v, --verbose\n: Output the calculated dates to stderr.\n\n-h, --help\n: display usage\n\n--timestamp *YY*-*MM*-*DD* *hh*-*mm*-*ss*|*@seconds*\n: Use *timestamp* for the initial start time instead of now.\n\n--stdin\n: Read crontab expression from stdin.\n\n# BUILDING\n\n## Quick Install\n\n```\nmake\n```\n\n## Selecting a Sandbox\n\n```\nRESTRICT_PROCESS=null make clean all\n```\n\n## Using musl libc\n\n```\n## Using the rlimit mode process restriction\nRESTRICT_PROCESS=rlimit ./musl-make\n\n## linux seccomp mode process restriction: requires kernel headers\n\n# clone the kernel headers somewhere\ncd /path/to/dir\ngit clone https://github.com/sabotage-linux/kernel-headers.git\n\n# then compile\nPSEUDOCRON_INCLUDE=/path/to/dir ./musl-make clean all\n```\n\n## Sandbox\n\nSetting the `RESTRICT_PROCESS` environment variable controls which\nmode of process restriction is used. The available modes are:\n\n* seccomp: linux\n\n* pledge: openbsd\n\n* capsicum: freebsd\n\n* rlimit: all\n\n* null: all\n\nFor example, to force using the rlimit process restriction:\n\n```\nRESTRICT_PROCESS=rlimit make clean all\n```\n\nThe `null` mode disables process restrictions and can be used for debugging.\n\n```\nRESTRICT_PROCESS=null make clean all\nstrace -o null.trace ./pseudcron ...\n\nRESTRICT_PROCESS=seccomp make clean all\nstrace -o seccomp.trace ./pseudcron ...\n```\n\n# ALTERNATIVES\n\n* [runcron](https://github.com/msantos/runcron)\n\n* [runwhen](http://code.dogmap.org/runwhen/)\n\n* [supercronic](https://github.com/aptible/supercronic)\n\n* [uschedule](https://ohse.de/uwe/uschedule.html)\n\n# SEE ALSO\n\n*crontab*(5), *sleep*(1)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmsantos%2Fpseudocron","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmsantos%2Fpseudocron","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmsantos%2Fpseudocron/lists"}