is `cap` a reserved word? - zsh completion? - zsh

I'm trying to create a Capistrano mutilstage completion for ZSH:
$ cap |
production staging
$ cap production |
deploy -- Deploy a new release
deploy:bundle -- Bundle
...
Completion code:
#compdef cap
#autoload
# /Users/pablo/.oh-my-zsh/custom/plugins/capistrano_custom/_capistrano_custom
local curcontext="$curcontext" state line ret=1
local -a _configs
_arguments -C \
'1: :->cmds' \
'2:: :->args' && ret=0
_cap_tasks() {
if [[ ! -f .cap_tasks~ ]]; then
echo "\nGenerating .cap_tasks~..." > /dev/stderr
cap -v --tasks | grep '#' | cut -d " " -f 2 > .cap_tasks~
fi
cat .cap_tasks~
}
_cap_stages() {
find config/deploy -name \*.rb | cut -d/ -f3 | sed s:.rb::g
}
case $state in
cmds)
if [[ -d config/deploy ]]; then
compadd `_cap_stages`
else
compadd `_cap_tasks`
fi
ret=0
;;
args)
compadd `_cap_tasks`
ret=0
;;
esac
return ret
The problem:
#compdef cap doesn't work. If I type cap and [TAB] it doesn't execute the completion, but with other words (i.e. shipit) works fine.
Any ideas?
Solution:
cap is really a reserved word and it seems that we can't use it with #compdef cap.
I'm wondering how cap and capistrano completions worked before (maybe an old version of ZSH).
Solution dotfiles code: capistrano_custom
Solution oh-my-zsh/PR: #2471
Both solutions use shipit instead of cap.
$ shipit |
production staging
$ shipit production |
deploy -- Deploy a new release
deploy:bundle -- Bundle
...

Yes, cap is a ZSH builtin. Quoting from zsh docs:
The zsh/cap module is used for manipulating POSIX.1e (POSIX.6)
capability sets. [...]. The builtins in this module are:
cap [ capabilities ] Change the shell’s process capability sets to the
specified capabilities, otherwise display the shell’s current
capabilities.

Related

How to Run a Shell Command in a zsh-theme?

So, I have Oh My Zsh up and running, and I'm creating my own new zsh-theme. In it, I wish to grab the external IP address from https://api.myip.com - and I'm using curl & grep to grab it. Works fine when I enter it at the command prompt, but when embedded in my zsh-theme file it gives me an error:
zsh: no matches found: ((1?[0-9][0-9]?|2[0-4][0-9]|25[0-5]).){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])
(23) Failed writing body
Jacobs-MacBook-Pro-2.local jacobjackson ttys002 0 [ ] 10/29/20 18:32:46 PM
Here is my zsh-theme:
PROMPT='%F{white}%M %n %y %j $(curl -s https://api.myip.com | grep -oE '((1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])') %F{green}%2c%F{blue} [%f '
RPROMPT='$(git_prompt_info) %F{blue}] %F{green}%W %* %F{yellow}%D{%p}%f'
ZSH_THEME_GIT_PROMPT_PREFIX="%F{yellow}"
ZSH_THEME_GIT_PROMPT_SUFFIX="%f"
ZSH_THEME_GIT_PROMPT_DIRTY=" %F{red}*%f"
ZSH_THEME_GIT_PROMPT_CLEAN=""
And here is the command sequence that grabs the IP address:
curl -s https://api.myip.com | grep -oE '((1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])'
Try this:
# Function name that's compatible with
# http://zsh.sourceforge.net/Doc/Release/User-Contributions.html#Prompt-Themes
# in case you ever want to build a full prompt theme.
# -s to prevent curl from outputting a progress bar.
# Use a service that simply outputs your IP, so you
# don't have to parse anything.
prompt_jacobjackson_precmd() {
psvar[1]=$( curl -s ifconfig.co )
}
# precmd hooks ru just before each new prompt.
autoload -Uz add-zsh-hook
add-zsh-hook precmd prompt_jacobjackson_precmd
# %1v inserts the 1st element of the psvar array. See
# http://zsh.sourceforge.net/Doc/Release/Prompt-Expansion.html#Conditional-Substrings-in-Prompts
PS1='%1v > '
I decided to use some of Marlon Richert's ideas as well a few from the zsh-theme 'bureau.' :)
get_space () {
local STR=$1$2
local zero='%([BSUbfksu]|([FB]|){*})'
local LENGTH=${#${(S%%)STR//$~zero/}}
local SPACES=""
(( LENGTH = ${COLUMNS} - $LENGTH - 1))
for i in {0..$LENGTH}
do
SPACES="$SPACES "
done
echo $SPACES
}
_1LEFT="%F{white}$(curl -s https://api.myip.com | jq .ip -r) %F{green}\$(dirs -c; dirs)"
_1RIGHT="%F{yellow}%j jobs %F{cyan}\$(~/systemstatus.sh)"
actionjackson_precmd () {
_1SPACES=`get_space $_1LEFT $_1RIGHT`
#print
print -rP "$_1LEFT$_1SPACES$_1RIGHT"
}
setopt prompt_subst
PROMPT='%F{yellow}%n%F{white}#%F{green}%M $_LIBERTY%f '
RPROMPT='$(actionjackson_git_prompt) %F{green}%W %* %F{yellow}%D{%p}%f'
autoload -U add-zsh-hook
add-zsh-hook precmd actionjackson_precmd

zsh function case condition parse error near `)'

I'm following this blog to setup a zsh function to switch aws cli profiles
: https://mads-hartmann.com/2017/04/27/multiple-aws-profiles.html
This is the zsh function in the blog:
function aws-switch() {
case ${1} in
"")
clear)
export AWS_PROFILE=""
;;
*)
export AWS_PROFILE="${1}"
;;
esac
}
#compdef aws-switch
#description Switch the AWS profile
_aws-switch() {
local -a aws_profiles
aws_profiles=$( \
grep '\[profile' ~/.aws/config \
| awk '{sub(/]/, "", $2); print $2}' \
| while read -r profile; do echo -n "$profile "; done \
)
_arguments \
':Aws profile:($(echo ${aws_profiles}) clear)'
}
_aws-switch "$#"
I added these lines to my ~/.zshrc, when I run source ~/.zshrc
It gives /.zshrc:4: parse error near `)'
I read the zsh function doc but still not very good at understanding the syntax and how could I fix this.
Have a look at the zsh man page (man zshmisc):
case word in [ [(] pattern [ | pattern ] ... ) list (;;|;&|;|) ] ... esac
As you see, you have to separate multiple pattern by |:
case $1 in
|clear)
....

Enter a command for a user

I have written a ZSH function whose output is a command line which runs a program I need the user to be able to interact with.
At the moment I just echo the command line and instruct the user to copy-paste it so that they have the necessary access to its pipes, however is there a way I can just have the function finish by entering the command for the user as if they had copied and pasted it themselves?
I have looked into using zle but that seems to require a key binding, whereas I just want the user to be able to run: myzshfunction arg1 and the ultimate result to be their terminal attached to the program launched as a result of some processing of their arg1.
$ myzshfunction arg2*2
Run this command! foobar baz4
$ foobar baz4
...
The function looks something like this:
myzshfunction() {
if [[ $# = 0 ]]
then
echo "usage: myzshfunction 1.2.3.4"
return
fi
local creds=`curl "https://xxx/$1/latest" | jq -r 'x'`
local cred_arr=("${(#s|/|)creds}")
local pwd_pipe=$(mktemp -u)
mkfifo $pwd_pipe
exec 3<>$pwd_pipe
rm $pwd_pipe
echo $cred_arr[2] >&3
echo "Run this: sshpass -d3 ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null "$cred_arr[1]#$1"
exec 3>&-
}
TIA
Use print -z to add text to the buffer. From the documentation:
-z Push the arguments onto the editing buffer stack, separated by spaces.
Calling foo, defined below, will result in hi being placed on the command line as if the user had typed it. For example,
% foo () { print -z hi; }
% foo
% hi
The best solution I could come up with was to use zle - the Zsh Line Editor.
This lets you update the command the user is currently editing, which to me feels a bit hacky. I would prefer a solution that lets you call a function, hit return, and then cleanly run a function with STDIO attached to your terminal as if you had run the resulting command line.
Perhaps you could emulate this by bindkey'ing the return key and doing some sort of decision/routing from there to see if the user wants to call myfunc. For now, my solution requires the Esc+i sequence is entered after typing a target for $host.
zle-myfunc() {
apikey=$(keychain-environment-variable api-key)
if [ $? -ne 0 ]; then
echo "Add your api-key to the keychain: "
BUFFER='security add-generic-password -U -a ${USER} -D "environment variable" -s "api-key" -w'
zle accept-line
return 1
fi
local host=$BUFFER
zle kill-buffer
local creds=`curl ..." | jq -r ...`
if [ -z creds ]; then
echo "Couldn't get creds, check your network"
return 1
fi
local creds_arr=("${(#s|/|)creds}")
local pwd_pipe=$(mktemp -u)
mkfifo $pwd_pipe
exec 3<>$pwd_pipe
# anonymise the pipe
rm $pwd_pipe
echo "$creds_arr[2]" >&3
BUFFER="sshpass -d3 ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null $creds_arr[1]#$host"
zle accept-line
# exec 3>&-
}
zle -N zle-myfunc
bindkey '\ei' zle-myfunc

zsh completion with virtual path

I want to create a zsh completion for a tool with a virtual file tree.
e.g. my file tree looks like the following:
/
|- foo/
| |- bar
| |- baz/
| |- qux
|- foobar
My tool mycmd has a subcommand for listing the current directory:
$ mycmd ls
foo/
foobar
$ mycmd ls foo/
bar
baz/
My actual zsh completion looks like this:
_mycmd_ls() {
if [ ! -z "$words[-1]" ]; then
dir=$(dirname /$words[-1])
lastpart=$(basename $words[-1])
items=$(mycmd ls $dir | grep "^$lastpart")
else
items=$(mycmd ls)
fi
_values -s ' ' 'items' ${(uozf)items}
}
_mycmd() {
local -a commands
commands=(
'ls:list items in directory'
)
_arguments -C -s -S -n \
'(- 1 *)'{-v,--version}"[Show program\'s version number and exit]: :->full" \
'(- 1 *)'{-h,--help}'[Show help message and exit]: :->full' \
'1:cmd:->cmds' \
'*:: :->args' \
case "$state" in
(cmds)
_describe -t commands 'commands' commands
;;
(args)
_mycmd_ls
;;
(*)
;;
esac
}
_mycmd
IMHO is _values the wrong utility function. The actual behaviour is:
$ mycmd ls<TAB>
foo/ foobar
$ mycmd ls foo/<TAB> ## <- it inserts automatically a space before <TAB> and so $words[-1] = ""
foo/ foobar
I can't use the utility function _files or _path_files because the file tree is only virtual.
I would suggest to make use of compadd rather _values to get in control of the suffix character appended. Then looking at the available choices, set an empty suffix character in case a virtual directory is part of the result:
_mycmd_ls() {
if [ ! -z "$words[-1]" ]; then
dir=$(dirname /$words[-1])
lastpart=$(basename $words[-1])
items=$(mycmd ls $dir | grep "^$lastpart")
else
items=$(mycmd ls)
fi
local suffix=' ';
# do not append space to word completed if it is a directory (ends with /)
for val in $items; do
if [ "${val: -1:1}" = '/' ]; then
suffix=''
break
fi
done
compadd -S "$suffix" -a items
}

How do I list all cron jobs for all users?

Is there a command or an existing script that will let me view all of a *NIX system's scheduled cron jobs at once? I'd like it to include all of the user crontabs, as well as /etc/crontab, and whatever's in /etc/cron.d. It would also be nice to see the specific commands run by run-parts in /etc/crontab.
Ideally, I'd like the output in a nice column form and ordered in some meaningful way.
I could then merge these listings from multiple servers to view the overall "schedule of events."
I was about to write such a script myself, but if someone's already gone to the trouble...
You would have to run this as root, but:
for user in $(cut -f1 -d: /etc/passwd); do crontab -u $user -l; done
will loop over each user name listing out their crontab. The crontabs are owned by the respective users so you won't be able to see another user's crontab w/o being them or root.
Edit
if you want to know which user a crontab belongs to, use echo $user
for user in $(cut -f1 -d: /etc/passwd); do echo $user; crontab -u $user -l; done
I ended up writing a script (I'm trying to teach myself the finer points of bash scripting, so that's why you don't see something like Perl here). It's not exactly a simple affair, but it does most of what I need. It uses Kyle's suggestion for looking up individual users' crontabs, but also deals with /etc/crontab (including the scripts launched by run-parts in /etc/cron.hourly, /etc/cron.daily, etc.) and the jobs in the /etc/cron.d directory. It takes all of those and merges them into a display something like the following:
mi h d m w user command
09,39 * * * * root [ -d /var/lib/php5 ] && find /var/lib/php5/ -type f -cmin +$(/usr/lib/php5/maxlifetime) -print0 | xargs -r -0 rm
47 */8 * * * root rsync -axE --delete --ignore-errors / /mirror/ >/dev/null
17 1 * * * root /etc/cron.daily/apt
17 1 * * * root /etc/cron.daily/aptitude
17 1 * * * root /etc/cron.daily/find
17 1 * * * root /etc/cron.daily/logrotate
17 1 * * * root /etc/cron.daily/man-db
17 1 * * * root /etc/cron.daily/ntp
17 1 * * * root /etc/cron.daily/standard
17 1 * * * root /etc/cron.daily/sysklogd
27 2 * * 7 root /etc/cron.weekly/man-db
27 2 * * 7 root /etc/cron.weekly/sysklogd
13 3 * * * archiver /usr/local/bin/offsite-backup 2>&1
32 3 1 * * root /etc/cron.monthly/standard
36 4 * * * yukon /home/yukon/bin/do-daily-stuff
5 5 * * * archiver /usr/local/bin/update-logs >/dev/null
Note that it shows the user, and more-or-less sorts by hour and minute so that I can see the daily schedule.
So far, I've tested it on Ubuntu, Debian, and Red Hat AS.
#!/bin/bash
# System-wide crontab file and cron job directory. Change these for your system.
CRONTAB='/etc/crontab'
CRONDIR='/etc/cron.d'
# Single tab character. Annoyingly necessary.
tab=$(echo -en "\t")
# Given a stream of crontab lines, exclude non-cron job lines, replace
# whitespace characters with a single space, and remove any spaces from the
# beginning of each line.
function clean_cron_lines() {
while read line ; do
echo "${line}" |
egrep --invert-match '^($|\s*#|\s*[[:alnum:]_]+=)' |
sed --regexp-extended "s/\s+/ /g" |
sed --regexp-extended "s/^ //"
done;
}
# Given a stream of cleaned crontab lines, echo any that don't include the
# run-parts command, and for those that do, show each job file in the run-parts
# directory as if it were scheduled explicitly.
function lookup_run_parts() {
while read line ; do
match=$(echo "${line}" | egrep -o 'run-parts (-{1,2}\S+ )*\S+')
if [[ -z "${match}" ]] ; then
echo "${line}"
else
cron_fields=$(echo "${line}" | cut -f1-6 -d' ')
cron_job_dir=$(echo "${match}" | awk '{print $NF}')
if [[ -d "${cron_job_dir}" ]] ; then
for cron_job_file in "${cron_job_dir}"/* ; do # */ <not a comment>
[[ -f "${cron_job_file}" ]] && echo "${cron_fields} ${cron_job_file}"
done
fi
fi
done;
}
# Temporary file for crontab lines.
temp=$(mktemp) || exit 1
# Add all of the jobs from the system-wide crontab file.
cat "${CRONTAB}" | clean_cron_lines | lookup_run_parts >"${temp}"
# Add all of the jobs from the system-wide cron directory.
cat "${CRONDIR}"/* | clean_cron_lines >>"${temp}" # */ <not a comment>
# Add each user's crontab (if it exists). Insert the user's name between the
# five time fields and the command.
while read user ; do
crontab -l -u "${user}" 2>/dev/null |
clean_cron_lines |
sed --regexp-extended "s/^((\S+ +){5})(.+)$/\1${user} \3/" >>"${temp}"
done < <(cut --fields=1 --delimiter=: /etc/passwd)
# Output the collected crontab lines. Replace the single spaces between the
# fields with tab characters, sort the lines by hour and minute, insert the
# header line, and format the results as a table.
cat "${temp}" |
sed --regexp-extended "s/^(\S+) +(\S+) +(\S+) +(\S+) +(\S+) +(\S+) +(.*)$/\1\t\2\t\3\t\4\t\5\t\6\t\7/" |
sort --numeric-sort --field-separator="${tab}" --key=2,1 |
sed "1i\mi\th\td\tm\tw\tuser\tcommand" |
column -s"${tab}" -t
rm --force "${temp}"
Under Ubuntu or debian, you can view crontab by /var/spool/cron/crontabs/ and then a file for each user is in there. That's only for user-specific crontab's of course.
For Redhat 6/7 and Centos, the crontab is under /var/spool/cron/.
This will show all crontab entries from all users.
sed 's/^\([^:]*\):.*$/crontab -u \1 -l 2>\&1/' /etc/passwd | sh | grep -v "no crontab for"
Depends on your linux version but I use:
tail -n 1000 /var/spool/cron/*
as root. Very simple and very short.
Gives me output like:
==> /var/spool/cron/root <==
15 2 * * * /bla
==> /var/spool/cron/my_user <==
*/10 1 * * * /path/to/script
A small refinement of Kyle Burton's answer with improved output formatting:
#!/bin/bash
for user in $(cut -f1 -d: /etc/passwd)
do echo $user && crontab -u $user -l
echo " "
done
getent passwd | cut -d: -f1 | perl -e'while(<>){chomp;$l = `crontab -u $_ -l 2>/dev/null`;print "$_\n$l\n" if $l}'
This avoids messing with passwd directly, skips users that have no cron entries and for those who have them it prints out the username as well as their crontab.
Mostly dropping this here though so i can find it later in case i ever need to search for it again.
To get list from ROOT user.
for user in $(cut -f1 -d: /etc/passwd); do echo $user; sudo crontab -u $user -l; done
If you check a cluster using NIS, the only way to see if a user has a crontab entry ist according to Matt's answer /var/spool/cron/tabs.
grep -v "#" -R /var/spool/cron/tabs
I like the simple one-liner answer above:
for user in $(cut -f1 -d: /etc/passwd); do crontab -u $user -l; done
But Solaris which does not have the -u flag and does not print the user it's checking, you can modify it like so:
for user in $(cut -f1 -d: /etc/passwd); do echo User:$user; crontab -l $user 2>&1 | grep -v crontab; done
You will get a list of users without the errors thrown by crontab when an account is not allowed to use cron etc. Be aware that in Solaris, roles can be in /etc/passwd too (see /etc/user_attr).
This script worked for me in CentOS to list all crons in the environment:
sudo cat /etc/passwd | sed 's/^\([^:]*\):.*$/sudo crontab -u \1 -l 2>\&1/' | grep -v "no crontab for" | sh
While many of the answers produce useful results, I think the hustle of maintaining a complex script for this task is not worth it. This is mainly because most distros use different cron daemons.
Watch and learn, kids & elders.
$ \cat ~jaroslav/bin/ls-crons
#!/bin/bash
getent passwd | awk -F: '{ print $1 }' | xargs -I% sh -c 'crontab -l -u % | sed "/^$/d; /^#/d; s/^/% /"' 2>/dev/null
echo
cat /etc/crontab /etc/anacrontab 2>/dev/null | sed '/^$/d; /^#/d;'
echo
run-parts --list /etc/cron.hourly;
run-parts --list /etc/cron.daily;
run-parts --list /etc/cron.weekly;
run-parts --list /etc/cron.monthly;
Run like this
$ sudo ls-cron
Sample output (Gentoo)
$ sudo ~jaroslav/bin/ls-crons
jaroslav */5 * * * * mv ~/java_error_in_PHPSTORM* ~/tmp 2>/dev/null
jaroslav 5 */24 * * * ~/bin/Find-home-files
jaroslav * 7 * * * cp /T/fortrabbit/ssh-config/fapps.tsv /home/jaroslav/reference/fortrabbit/fapps
jaroslav */8 1 * * * make -C /T/fortrabbit/ssh-config discover-apps # >/dev/null
jaroslav */7 * * * * getmail -r jazzoslav -r fortrabbit 2>/dev/null
jaroslav */1 * * * * /home/jaroslav/bin/checkmail
jaroslav * 9-18 * * * getmail -r fortrabbit 2>/dev/null
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
HOME=/
SHELL=/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
RANDOM_DELAY=45
START_HOURS_RANGE=3-22
1 5 cron.daily nice run-parts /etc/cron.daily
7 25 cron.weekly nice run-parts /etc/cron.weekly
#monthly 45 cron.monthly nice run-parts /etc/cron.monthly
/etc/cron.hourly/0anacron
/etc/cron.daily/logrotate
/etc/cron.daily/man-db
/etc/cron.daily/mlocate
/etc/cron.weekly/mdadm
/etc/cron.weekly/pfl
Sample output (Ubuntu)
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
17 * * * * root cd / && run-parts --report /etc/cron.hourly
25 6 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
/etc/cron.hourly/btrfs-quota-cleanup
/etc/cron.hourly/ntpdate-debian
/etc/cron.daily/apport
/etc/cron.daily/apt-compat
/etc/cron.daily/apt-show-versions
/etc/cron.daily/aptitude
/etc/cron.daily/bsdmainutils
/etc/cron.daily/dpkg
/etc/cron.daily/logrotate
/etc/cron.daily/man-db
/etc/cron.daily/mlocate
/etc/cron.daily/passwd
/etc/cron.daily/popularity-contest
/etc/cron.daily/ubuntu-advantage-tools
/etc/cron.daily/update-notifier-common
/etc/cron.daily/upstart
/etc/cron.weekly/apt-xapian-index
/etc/cron.weekly/man-db
/etc/cron.weekly/update-notifier-common
Pics
Ubuntu:
Gentoo:
for user in $(cut -f1 -d: /etc/passwd);
do
echo $user; crontab -u $user -l;
done
The following strips away comments, empty lines, and errors from users with no crontab. All you're left with is a clear list of users and their jobs.
Note the use of sudo in the 2nd line. If you're already root, remove that.
for USER in $(cut -f1 -d: /etc/passwd); do \
USERTAB="$(sudo crontab -u "$USER" -l 2>&1)"; \
FILTERED="$(echo "$USERTAB"| grep -vE '^#|^$|no crontab for|cannot use this program')"; \
if ! test -z "$FILTERED"; then \
echo "# ------ $(tput bold)$USER$(tput sgr0) ------"; \
echo "$FILTERED"; \
echo ""; \
fi; \
done
Example output:
# ------ root ------
0 */6 * * * /usr/local/bin/disk-space-notify.sh
45 3 * * * /opt/mysql-backups/mysql-backups.sh
5 7 * * * /usr/local/bin/certbot-auto renew --quiet --no-self-upgrade
# ------ sammy ------
55 * * * * wget -O - -q -t 1 https://www.example.com/cron.php > /dev/null
I use this on Ubuntu (12 thru 16) and Red Hat (5 thru 7).
On Solaris, for a particular known user name:
crontab -l username
To get all user's jobs at once on Solaris, much like other posts above:
for user in $(cut -f1 -d: /etc/passwd); do crontab -l $user 2>/dev/null; done
Update:
Please stop suggesting edits that are wrong on Solaris:
Depends on your version of cron. Using Vixie cron on FreeBSD, I can do something like this:
(cd /var/cron/tabs && grep -vH ^# *)
if I want it more tab deliminated, I might do something like this:
(cd /var/cron/tabs && grep -vH ^# * | sed "s/:/ /")
Where that's a literal tab in the sed replacement portion.
It may be more system independent to loop through the users in /etc/passwd and do crontab -l -u $user for each of them.
you can write for all user list :
sudo crontab -u userName -l
,
You can also go to
cd /etc/cron.daily/
ls -l
cat filename
this file will list the schedules
cd /etc/cron.d/
ls -l
cat filename
i made below one liner script and it worked for me to list all cron jobs for all users.
cat /etc/passwd |awk -F ':' '{print $1}'|while read a;do crontab -l -u ${a} ; done
Thanks for this very useful script. I had some tiny problems running it on old systems (Red Hat Enterprise 3, which handle differently egrep and tabs in strings), and other systems with nothing in /etc/cron.d/ (the script then ended with an error). So here is a patch to make it work in such cases :
2a3,4
> #See: http://stackoverflow.com/questions/134906/how-do-i-list-all-cron-jobs-for-all-users
>
27c29,30
< match=$(echo "${line}" | egrep -o 'run-parts (-{1,2}\S+ )*\S+')
---
> #match=$(echo "${line}" | egrep -o 'run-parts (-{1,2}\S+ )*\S+')
> match=$(echo "${line}" | egrep -o 'run-parts.*')
51c54,57
< cat "${CRONDIR}"/* | clean_cron_lines >>"${temp}" # */ <not a comment>
---
> sys_cron_num=$(ls /etc/cron.d | wc -l | awk '{print $1}')
> if [ "$sys_cron_num" != 0 ]; then
> cat "${CRONDIR}"/* | clean_cron_lines >>"${temp}" # */ <not a comment>
> fi
67c73
< sed "1i\mi\th\td\tm\tw\tuser\tcommand" |
---
> sed "1i\mi${tab}h${tab}d${tab}m${tab}w${tab}user${tab}command" |
I'm not really sure the changes in the first egrep are a good idea, but well, this script has been tested on RHEL3,4,5 and Debian5 without any problem. Hope this helps!
Building on top of #Kyle
for user in $(tail -n +11 /etc/passwd | cut -f1 -d:); do echo $user; crontab -u $user -l; done
to avoid the comments usually at the top of /etc/passwd,
And on macosx
for user in $(dscl . -list /users | cut -f1 -d:); do echo $user; crontab -u $user -l; done
I think a better one liner would be below. For example if you have users in NIS or LDAP they wouldnt be in /etc/passwd. This will give you the crontabs of every user that has logged in.
for I in `lastlog | grep -v Never | cut -f1 -d' '`; do echo $I ; crontab -l -u $I ; done
With apologies and thanks to yukondude.
I've tried to summarise the timing settings for easy reading, though it's not a perfect job, and I don't touch 'every Friday' or 'only on Mondays' stuff.
This is version 10 - it now:
runs much much faster
has optional progress characters so you could improve the speed further.
uses a divider line to separate header and output.
outputs in a compact format when all timing intervals uencountered can be summarised.
Accepts Jan...Dec descriptors for months-of-the-year
Accepts Mon...Sun descriptors for days-of-the-week
tries to handle debian-style dummying-up of anacron when it is missing
tries to deal with crontab lines which run a file after pre-testing executability using "[ -x ... ]"
tries to deal with crontab lines which run a file after pre-testing executability using "command -v"
allows the use of interval spans and lists.
supports run-parts usage in user-specific /var/spool crontab files.
I am now publishing the script in full here.
https://gist.github.com/myshkin-uk/d667116d3e2d689f23f18f6cd3c71107
Since it is a matter of looping through a file (/etc/passwd) and performing an action, I am missing the proper approach on How can I read a file (data stream, variable) line-by-line (and/or field-by-field)?:
while IFS=":" read -r user _
do
echo "crontab for user ${user}:"
crontab -u "$user" -l
done < /etc/passwd
This reads /etc/passwd line by line using : as field delimiter. By saying read -r user _, we make $user hold the first field and _ the rest (it is just a junk variable to ignore fields).
This way, we can then call crontab -u using the variable $user, which we quote for safety (what if it contains spaces? It is unlikely in such file, but you can never know).
I tend to use following small commands to list all jobs for single user and all users on Unix based operating systems with a modern bash console:
1. Single user
echo "Jobs owned by $USER" && crontab -l -u $USER
2. All users
for wellknownUser in $(cut -f1 -d: /etc/passwd);
do
echo "Jobs owned by $wellknownUser";
crontab -l -u $wellknownUser;
echo -e "\n";
sleep 2; # (optional sleep 2 seconds) while drinking a coffee
done
This script outputs the Crontab to a file and also lists all users confirming those which have no crontab entry:
for user in $(cut -f1 -d: /etc/passwd); do
echo $user >> crontab.bak
echo "" >> crontab.bak
crontab -u $user -l >> crontab.bak 2>> > crontab.bak
done

Resources