Merge pull request #1460 from lzybkr/jasonsh/CronTab-Demo

Add crontab demo
This commit is contained in:
Bruce Payette 2016-07-21 11:10:02 -07:00 committed by GitHub
commit c8c4f06e63
7 changed files with 185 additions and 36 deletions

View file

@ -1,9 +0,0 @@
# Use the crontab module available at ./modules/CronTab
# Get the existing cron jobs
# Sort them by data
# Create a new one using a DateTime object
# Show in bash that the new cron job exists

View file

@ -0,0 +1,61 @@
@{
# Script module or binary module file associated with this manifest.
RootModule = 'CronTab.psm1'
# Version number of this module.
ModuleVersion = '0.1.0.0'
# Supported PSEditions
CompatiblePSEditions = @('Linux')
# ID used to uniquely identify this module
GUID = '508bb97f-de2e-482e-aae2-01caec0be8c7'
# Author of this module
Author = 'Microsoft'
# Company or vendor of this module
CompanyName = 'Unknown'
# Copyright statement for this module
Copyright = '(c) 2016 Microsoft. All rights reserved.'
# Description of the functionality provided by this module
Description = 'Sample module for managing CronTab'
# Format files (.ps1xml) to be loaded when importing this module
FormatsToProcess = 'CronTab.ps1xml'
# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export.
FunctionsToExport = 'New-CronJob','Remove-CronJob','Get-CronJob','Get-CronTabUser'
# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell.
PrivateData = @{
PSData = @{
# Tags applied to this module. These help with module discovery in online galleries.
# Tags = @()
# A URL to the license for this module.
# LicenseUri = ''
# A URL to the main website for this project.
# ProjectUri = ''
# A URL to an icon representing this module.
# IconUri = ''
# ReleaseNotes of this module
# ReleaseNotes = ''
} # End of PSData hashtable
} # End of PrivateData hashtable
# HelpInfo URI of this module
# HelpInfoURI = ''
}

View file

@ -1,22 +1,31 @@
using namespace System.Collections.Generic
using namespace System.Management.Automation
$crontabcmd = "/usr/bin/crontab"
#TODO fix after https://github.com/PowerShell/PowerShell/issues/932 is fixed
#class CronJob {
# [string] $Minute
# [string] $Hour
# [string] $DayOfMonth
# [string] $Month
# [string] $DayOfWeek
# [string] $Command
#}
class CronJob {
[string] $Minute
[string] $Hour
[string] $DayOfMonth
[string] $Month
[string] $DayOfWeek
[string] $Command
[string] ToString()
{
return "{0} {1} {2} {3} {4} {5}" -f
$this.Minute, $this.Hour, $this.DayOfMonth, $this.Month, $this.DayOfWeek, $this.Command
}
}
# Internal helper functions
function Get-CronTab ([String] $user) {
$crontab = Invoke-CronTab -user $user -arguments "-l" -noThrow
if ($crontab -is [System.Management.Automation.ErrorRecord]) {
if ($crontab -is [ErrorRecord]) {
if ($crontab.Exception.Message.StartsWith("no crontab for ")) {
$crontab = $null
$crontab = @()
}
else {
throw $crontab.Exception
@ -27,8 +36,7 @@ function Get-CronTab ([String] $user) {
function ConvertTo-CronJob ([String] $crontab) {
$split = $crontab.split(" ", 6)
$cronjob = New-Object -TypeName PSObject -Property @{ #TODO: change to CronJob type
PSTypeName="CronJob";
$cronjob = [CronJob]@{
Minute = $split[0];
Hour = $split[1];
DayOfMonth= $split[2];
@ -39,14 +47,13 @@ function ConvertTo-CronJob ([String] $crontab) {
$cronjob
}
function Invoke-CronTab ([String] $user, [String] $arguments, [Switch] $noThrow) {
function Invoke-CronTab ([String] $user, [String[]] $arguments, [Switch] $noThrow) {
If ($user -ne [String]::Empty) {
$arguments = "-u $UserName $arguments"
$arguments = Write-Output "-u" $UserName $arguments
}
$cmd = "$crontabcmd $arguments 2>&1"
Write-Verbose $cmd
$output = Invoke-Expression $cmd
Write-Verbose "Running: $crontabcmd $arguments"
$output = & $crontabcmd @arguments 2>&1
if ($LastExitCode -ne 0 -and -not $noThrow) {
$e = New-Object System.InvalidOperationException -ArgumentList $output.Exception.Message
throw $e
@ -78,24 +85,37 @@ function Remove-CronJob {
Optional parameter to specify a specific user's cron table
.PARAMETER Job
Cron job object returned from Get-CronJob
.PARAMETER Force
Don't prompt when removing the cron job
#>
[CmdletBinding(SupportsShouldProcess=$true,ConfirmImpact="High")]
param (
[Alias("u")][Parameter(Mandatory=$false)][String] $UserName,
[Alias("j")][Parameter(Mandatory=$true,ValueFromPipeline=$true)][PSTypeName("CronJob")] $Job #TODO use CronJob type
[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]
$Job,
[Switch]
$Force
)
process {
[string[]] $crontab = Get-CronTab -user $UserName
[string[]] $newcrontab = $null
$newcrontab = [List[string]]::new()
$found = $false
$JobAsString = $Job.ToString()
foreach ($line in $crontab) {
$cronjob = ConvertTo-CronJob -crontab $line
if ((Compare-object $cronjob.psobject.properties $Job.psobject.properties) -eq $null) {
if ($JobAsString -ceq $line) {
$found = $true
} else {
$newcrontab += $line
$newcrontab.Add($line)
}
}
@ -103,7 +123,7 @@ function Remove-CronJob {
$e = New-Object System.Exception -ArgumentList "Job not found"
throw $e
}
if ($pscmdlet.ShouldProcess($Job.Command,"Remove")) {
if ($Force -or $pscmdlet.ShouldProcess($Job.Command,"Remove")) {
Import-CronTab -user $UserName -crontab $newcrontab
}
}
@ -140,7 +160,12 @@ function New-CronJob {
#>
[CmdletBinding()]
param (
[Alias("u")][Parameter(Mandatory=$false)][String] $UserName,
[ArgumentCompleter( { $wordToComplete = $args[2]; Get-CronTabUser | Where-Object { $_ -like "$wordToComplete*" } | Sort-Object } )]
[Alias("u")]
[Parameter(Mandatory=$false)]
[String]
$UserName,
[Alias("mi")][Parameter(Position=1)][String[]] $Minute = "*",
[Alias("h")][Parameter(Position=2)][String[]] $Hour = "*",
[Alias("dm")][Parameter(Position=3)][String[]] $DayOfMonth = "*",
@ -173,7 +198,7 @@ function Get-CronJob {
Optional parameter to specify a specific user's cron table
#>
[CmdletBinding()]
[OutputType([PSObject])]
[OutputType([CronJob])]
param (
[Alias("u")][Parameter(Mandatory=$false)][String] $UserName
)
@ -187,3 +212,33 @@ function Get-CronJob {
}
}
}
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
}
}
}

15
demos/crontab/README.md Normal file
View file

@ -0,0 +1,15 @@
## CronTab demo
This demo shows examining, creating, and removing cron jobs via crontab.
Output of Get-CronJob is a strongly typed object with properties like DayOfWeek or Command.
Remove-CronJob prompts before removing the job unless you specifiy -Force.
Tab completion of -UserName is supported, e.g.
Get-CronJob -u <TAB>
NYI: no way to run crontab with sudo if necessary
NYI: ignoring shell variables or comments
NYI: New-CronJob -Description "..." (save in comments"
NYI: @reboot,@daily,@hourly,etc

27
demos/crontab/crontab.ps1 Normal file
View file

@ -0,0 +1,27 @@
Import-Module $PSScriptRoot/CronTab/CronTab.psd1
Write-Host -Foreground Yellow "Remove all jobs to start, no prompting"
Get-CronJob | Remove-CronJob -Force
Write-Host -Foreground Yellow "Get the existing cron jobs"
Get-CronJob | Out-Host
Write-Host -Foreground Yellow "New cron job to clean out tmp every day at 1am"
New-CronJob -Command 'rm -rf /tmp/*' -Hour 1 | Out-Host
Write-Host -Foreground Yellow "Add some more jobs"
New-CronJob -Command 'python -c ~/scripts/backup_users' -Hour 2 -DayOfWeek 1-5 | Out-Host
New-CronJob -Command 'powershell -c "cd ~/src/PowerShell; ipmo ./build.psm1; Start-PSBuild"' -Hour 2 -DayOfWeek * | Out-Host
Write-Host -Foreground Yellow "Show in bash that the new cron job exists"
crontab -l
Write-Host -Foreground Yellow "Get jobs that run every day"
Get-CronJob | Where-Object { $_.DayOfWeek -eq '*' -or $_.DayOfWeek -eq '1-7' } | Out-Host
Write-Host -Foreground Yellow "Remove one cron job, with prompting to confirm"
Get-CronJob | Where-Object { $_.Command -match '^powershell.*' } | Remove-CronJob | Out-Host
Write-Host -Foreground Yellow "And the other job remains"
Get-CronJob | Out-Host

Binary file not shown.