2020-03-24 19:08:37 +01:00
|
|
|
# Copyright (c) Microsoft Corporation.
|
2018-02-13 18:23:53 +01:00
|
|
|
# Licensed under the MIT License.
|
2016-07-20 22:49:44 +02:00
|
|
|
|
|
|
|
using namespace System.Collections.Generic
|
2016-07-21 17:44:36 +02:00
|
|
|
using namespace System.Management.Automation
|
2016-07-20 22:49:44 +02:00
|
|
|
|
2016-07-13 01:54:08 +02:00
|
|
|
$crontabcmd = "/usr/bin/crontab"
|
|
|
|
|
2016-07-19 21:19:56 +02:00
|
|
|
class CronJob {
|
|
|
|
[string] $Minute
|
|
|
|
[string] $Hour
|
|
|
|
[string] $DayOfMonth
|
|
|
|
[string] $Month
|
|
|
|
[string] $DayOfWeek
|
|
|
|
[string] $Command
|
2016-07-21 18:18:28 +02:00
|
|
|
|
|
|
|
[string] ToString()
|
|
|
|
{
|
|
|
|
return "{0} {1} {2} {3} {4} {5}" -f
|
|
|
|
$this.Minute, $this.Hour, $this.DayOfMonth, $this.Month, $this.DayOfWeek, $this.Command
|
|
|
|
}
|
2016-07-19 21:19:56 +02:00
|
|
|
}
|
2016-07-13 01:54:08 +02:00
|
|
|
|
|
|
|
# Internal helper functions
|
|
|
|
|
|
|
|
function Get-CronTab ([String] $user) {
|
|
|
|
$crontab = Invoke-CronTab -user $user -arguments "-l" -noThrow
|
2016-07-21 17:44:36 +02:00
|
|
|
if ($crontab -is [ErrorRecord]) {
|
2016-07-13 01:54:08 +02:00
|
|
|
if ($crontab.Exception.Message.StartsWith("no crontab for ")) {
|
2016-07-20 22:49:44 +02:00
|
|
|
$crontab = @()
|
2016-07-13 01:54:08 +02:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
throw $crontab.Exception
|
|
|
|
}
|
|
|
|
}
|
|
|
|
[string[]] $crontab
|
|
|
|
}
|
|
|
|
|
|
|
|
function ConvertTo-CronJob ([String] $crontab) {
|
2016-11-28 23:01:45 +01:00
|
|
|
$split = $crontab -split " ", 6
|
2016-07-19 21:19:56 +02:00
|
|
|
$cronjob = [CronJob]@{
|
2016-07-13 01:54:08 +02:00
|
|
|
Minute = $split[0];
|
|
|
|
Hour = $split[1];
|
|
|
|
DayOfMonth= $split[2];
|
|
|
|
Month =$split[3];
|
|
|
|
DayOfWeek = $split[4];
|
|
|
|
Command = $split[5]
|
|
|
|
}
|
|
|
|
$cronjob
|
|
|
|
}
|
|
|
|
|
2016-07-21 18:40:03 +02:00
|
|
|
function Invoke-CronTab ([String] $user, [String[]] $arguments, [Switch] $noThrow) {
|
2016-07-13 01:54:08 +02:00
|
|
|
If ($user -ne [String]::Empty) {
|
2016-07-21 18:40:03 +02:00
|
|
|
$arguments = Write-Output "-u" $UserName $arguments
|
2016-07-13 01:54:08 +02:00
|
|
|
}
|
2017-01-16 22:31:14 +01:00
|
|
|
|
2016-07-21 18:40:03 +02:00
|
|
|
Write-Verbose "Running: $crontabcmd $arguments"
|
|
|
|
$output = & $crontabcmd @arguments 2>&1
|
2020-01-13 20:15:45 +01:00
|
|
|
if ($LASTEXITCODE -ne 0 -and -not $noThrow) {
|
2016-07-13 01:54:08 +02:00
|
|
|
$e = New-Object System.InvalidOperationException -ArgumentList $output.Exception.Message
|
|
|
|
throw $e
|
|
|
|
} else {
|
|
|
|
$output
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function Import-CronTab ([String] $user, [String[]] $crontab) {
|
|
|
|
$temp = New-TemporaryFile
|
|
|
|
[String]::Join([Environment]::NewLine,$crontab) | Set-Content $temp.FullName
|
|
|
|
Invoke-CronTab -user $user $temp.FullName
|
|
|
|
Remove-Item $temp
|
|
|
|
}
|
|
|
|
|
|
|
|
# Public functions
|
|
|
|
|
|
|
|
function Remove-CronJob {
|
|
|
|
<#
|
|
|
|
.SYNOPSIS
|
|
|
|
Removes the exactly matching cron job from the cron table
|
2020-10-02 13:54:15 +02:00
|
|
|
|
2016-07-13 01:54:08 +02:00
|
|
|
.DESCRIPTION
|
|
|
|
Removes the exactly matching cron job from the cron table
|
2020-10-02 13:54:15 +02:00
|
|
|
|
2016-07-13 01:54:08 +02:00
|
|
|
.EXAMPLE
|
2017-07-22 06:03:49 +02:00
|
|
|
Get-CronJob | Where-Object {%_.Command -like 'foo *'} | Remove-CronJob
|
2020-10-02 13:54:15 +02:00
|
|
|
|
2016-07-13 01:54:08 +02:00
|
|
|
.RETURNVALUE
|
|
|
|
None
|
2020-10-02 13:54:15 +02:00
|
|
|
|
2016-07-13 01:54:08 +02:00
|
|
|
.PARAMETER UserName
|
|
|
|
Optional parameter to specify a specific user's cron table
|
2020-10-02 13:54:15 +02:00
|
|
|
|
2016-07-13 01:54:08 +02:00
|
|
|
.PARAMETER Job
|
|
|
|
Cron job object returned from Get-CronJob
|
2020-10-02 13:54:15 +02:00
|
|
|
|
2016-07-21 18:55:48 +02:00
|
|
|
.PARAMETER Force
|
|
|
|
Don't prompt when removing the cron job
|
2017-01-16 22:31:14 +01:00
|
|
|
#>
|
2016-07-13 01:54:08 +02:00
|
|
|
[CmdletBinding(SupportsShouldProcess=$true,ConfirmImpact="High")]
|
|
|
|
param (
|
2016-07-21 17:44:36 +02:00
|
|
|
[ArgumentCompleter( { $wordToComplete = $args[2]; Get-CronTabUser | Where-Object { $_ -like "$wordToComplete*" } | Sort-Object } )]
|
|
|
|
[Alias("u")]
|
|
|
|
[Parameter(Mandatory=$false)]
|
|
|
|
[String]
|
|
|
|
$UserName,
|
|
|
|
|
|
|
|
[Alias("j")]
|
|
|
|
[Parameter(Mandatory=$true,ValueFromPipeline=$true)]
|
|
|
|
[CronJob]
|
2016-07-21 18:55:48 +02:00
|
|
|
$Job,
|
|
|
|
|
|
|
|
[Switch]
|
|
|
|
$Force
|
2016-07-13 01:54:08 +02:00
|
|
|
)
|
|
|
|
process {
|
|
|
|
|
|
|
|
[string[]] $crontab = Get-CronTab -user $UserName
|
2016-07-20 22:49:44 +02:00
|
|
|
$newcrontab = [List[string]]::new()
|
2016-07-13 01:54:08 +02:00
|
|
|
$found = $false
|
2017-01-16 22:31:14 +01:00
|
|
|
|
2016-07-21 18:18:28 +02:00
|
|
|
$JobAsString = $Job.ToString()
|
2016-07-13 01:54:08 +02:00
|
|
|
foreach ($line in $crontab) {
|
2016-07-21 18:18:28 +02:00
|
|
|
if ($JobAsString -ceq $line) {
|
2016-07-13 01:54:08 +02:00
|
|
|
$found = $true
|
|
|
|
} else {
|
2016-07-20 22:49:44 +02:00
|
|
|
$newcrontab.Add($line)
|
2016-07-13 01:54:08 +02:00
|
|
|
}
|
|
|
|
}
|
2017-01-16 22:31:14 +01:00
|
|
|
|
2016-07-13 01:54:08 +02:00
|
|
|
if (-not $found) {
|
|
|
|
$e = New-Object System.Exception -ArgumentList "Job not found"
|
|
|
|
throw $e
|
|
|
|
}
|
2020-01-13 20:19:12 +01:00
|
|
|
if ($Force -or $PSCmdlet.ShouldProcess($Job.Command,"Remove")) {
|
2016-07-13 01:54:08 +02:00
|
|
|
Import-CronTab -user $UserName -crontab $newcrontab
|
|
|
|
}
|
2017-01-16 22:31:14 +01:00
|
|
|
}
|
2016-07-13 01:54:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
function New-CronJob {
|
|
|
|
<#
|
|
|
|
.SYNOPSIS
|
|
|
|
Create a new cron job
|
|
|
|
.DESCRIPTION
|
|
|
|
Create a new job in the cron table. Date and time parameters can be specified
|
|
|
|
as ranges such as 10-30, as a list: 5,6,7, or combined 1-5,10-15. An asterisk
|
2017-01-16 22:31:14 +01:00
|
|
|
means 'first through last' (the entire allowed range). Step values can be used
|
2016-07-13 01:54:08 +02:00
|
|
|
with ranges or with an asterisk. Every 2 hours can be specified as either
|
|
|
|
0-23/2 or */2.
|
|
|
|
.EXAMPLE
|
|
|
|
New-CronJob -Minute 10-30 -Hour 10-20/2 -DayOfMonth */2 -Command "/bin/bash -c 'echo hello' > ~/hello"
|
2020-10-02 13:54:15 +02:00
|
|
|
|
2016-07-13 01:54:08 +02:00
|
|
|
.RETURNVALUE
|
|
|
|
If successful, an object representing the cron job is returned
|
2020-10-02 13:54:15 +02:00
|
|
|
|
2016-07-13 01:54:08 +02:00
|
|
|
.PARAMETER UserName
|
|
|
|
Optional parameter to specify a specific user's cron table
|
2020-10-02 13:54:15 +02:00
|
|
|
|
2016-07-13 01:54:08 +02:00
|
|
|
.PARAMETER Minute
|
|
|
|
Valid values are 0 to 59. If not specified, defaults to *.
|
2020-10-02 13:54:15 +02:00
|
|
|
|
2016-07-13 01:54:08 +02:00
|
|
|
.PARAMETER Hour
|
|
|
|
Valid values are 0-23. If not specified, defaults to *.
|
2020-10-02 13:54:15 +02:00
|
|
|
|
2016-07-13 01:54:08 +02:00
|
|
|
.PARAMETER DayOfMonth
|
|
|
|
Valid values are 1-31. If not specified, defaults to *.
|
2020-10-02 13:54:15 +02:00
|
|
|
|
2016-07-13 01:54:08 +02:00
|
|
|
.PARAMETER Month
|
|
|
|
Valid values are 1-12. If not specified, defaults to *.
|
2020-10-02 13:54:15 +02:00
|
|
|
|
2016-07-13 01:54:08 +02:00
|
|
|
.PARAMETER DayOfWeek
|
|
|
|
Valid values are 0-7. 0 and 7 are both Sunday. If not specified, defaults to *.
|
2020-10-02 13:54:15 +02:00
|
|
|
|
2016-07-13 01:54:08 +02:00
|
|
|
.PARAMETER Command
|
|
|
|
Command to execute at the scheduled time and day.
|
2017-01-16 22:31:14 +01:00
|
|
|
#>
|
2016-07-13 01:54:08 +02:00
|
|
|
[CmdletBinding()]
|
|
|
|
param (
|
2016-07-21 17:44:36 +02:00
|
|
|
[ArgumentCompleter( { $wordToComplete = $args[2]; Get-CronTabUser | Where-Object { $_ -like "$wordToComplete*" } | Sort-Object } )]
|
|
|
|
[Alias("u")]
|
|
|
|
[Parameter(Mandatory=$false)]
|
|
|
|
[String]
|
|
|
|
$UserName,
|
|
|
|
|
2016-07-13 01:54:08 +02:00
|
|
|
[Alias("mi")][Parameter(Position=1)][String[]] $Minute = "*",
|
|
|
|
[Alias("h")][Parameter(Position=2)][String[]] $Hour = "*",
|
|
|
|
[Alias("dm")][Parameter(Position=3)][String[]] $DayOfMonth = "*",
|
|
|
|
[Alias("mo")][Parameter(Position=4)][String[]] $Month = "*",
|
|
|
|
[Alias("dw")][Parameter(Position=5)][String[]] $DayOfWeek = "*",
|
|
|
|
[Alias("c")][Parameter(Mandatory=$true,Position=6)][String] $Command
|
|
|
|
)
|
|
|
|
process {
|
|
|
|
# TODO: validate parameters, note that different versions of crontab support different capabilities
|
2017-01-16 22:31:14 +01:00
|
|
|
$line = "{0} {1} {2} {3} {4} {5}" -f [String]::Join(",",$Minute), [String]::Join(",",$Hour),
|
2016-07-13 01:54:08 +02:00
|
|
|
[String]::Join(",",$DayOfMonth), [String]::Join(",",$Month), [String]::Join(",",$DayOfWeek), $Command
|
|
|
|
[string[]] $crontab = Get-CronTab -user $UserName
|
|
|
|
$crontab += $line
|
|
|
|
Import-CronTab -User $UserName -crontab $crontab
|
|
|
|
ConvertTo-CronJob -crontab $line
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function Get-CronJob {
|
|
|
|
<#
|
|
|
|
.SYNOPSIS
|
|
|
|
Returns the current cron jobs from the cron table
|
2020-10-02 13:54:15 +02:00
|
|
|
|
2016-07-13 01:54:08 +02:00
|
|
|
.DESCRIPTION
|
|
|
|
Returns the current cron jobs from the cron table
|
2020-10-02 13:54:15 +02:00
|
|
|
|
2016-07-13 01:54:08 +02:00
|
|
|
.EXAMPLE
|
|
|
|
Get-CronJob -UserName Steve
|
2020-10-02 13:54:15 +02:00
|
|
|
|
2016-07-13 01:54:08 +02:00
|
|
|
.RETURNVALUE
|
|
|
|
CronJob objects
|
2020-10-02 13:54:15 +02:00
|
|
|
|
2016-07-13 01:54:08 +02:00
|
|
|
.PARAMETER UserName
|
|
|
|
Optional parameter to specify a specific user's cron table
|
2017-01-16 22:31:14 +01:00
|
|
|
#>
|
2016-07-13 01:54:08 +02:00
|
|
|
[CmdletBinding()]
|
2016-07-19 21:19:56 +02:00
|
|
|
[OutputType([CronJob])]
|
2016-07-13 01:54:08 +02:00
|
|
|
param (
|
|
|
|
[Alias("u")][Parameter(Mandatory=$false)][String] $UserName
|
|
|
|
)
|
|
|
|
process {
|
|
|
|
$crontab = Get-CronTab -user $UserName
|
|
|
|
ForEach ($line in $crontab) {
|
|
|
|
if ($line.Trim().Length -gt 0)
|
|
|
|
{
|
|
|
|
ConvertTo-CronJob -crontab $line
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-07-21 17:44:36 +02:00
|
|
|
|
|
|
|
function Get-CronTabUser {
|
|
|
|
<#
|
|
|
|
.SYNOPSIS
|
|
|
|
Returns the users allowed to use crontab
|
|
|
|
#>
|
|
|
|
[CmdletBinding()]
|
|
|
|
[OutputType([String])]
|
|
|
|
param()
|
|
|
|
|
|
|
|
$allow = '/etc/cron.allow'
|
|
|
|
if (Test-Path $allow)
|
|
|
|
{
|
|
|
|
Get-Content $allow
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
$users = Get-Content /etc/passwd | ForEach-Object { ($_ -split ':')[0] }
|
|
|
|
$deny = '/etc/cron.deny'
|
|
|
|
if (Test-Path $deny)
|
|
|
|
{
|
|
|
|
$denyUsers = Get-Content $deny
|
|
|
|
$users | Where-Object { $denyUsers -notcontains $_ }
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
$users
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|