Bash Index : C - The 'C' Bash commands : description, flags and examples

mail

chcon

Usage

change file's SELinux security context

Flags

Flag Usage
-R --recursive operate on files and directories recursively
-t type --type=type set type type in the target security context
-v --verbose output a diagnostic for every file processed

Example

make files readable by Apache (details) :

chcon -Rt httpd_sys_content_t /data

mail

chage

Usage

change user password expiry information
Except for the -l option, chage is restricted to root.

Flags

Flag Usage
-E expireDate
--expiredate expireDate
Set the date on which the user's account will no longer be accessible (i.e. account will be locked) :
  • as a date in YYYY-MM-DD format
  • or as the number of days since January 1, 1970. -1 removes the account expiration date
A user whose account is locked must contact the system administrator before being able to use the system again.
-l --list Show account aging information (human-friendly version of passwd -S)

Example

Let's experiment :

  1. create a user account :
    adduser bob
  2. get account initial information :
    grep bob /etc/{passwd,shadow}
    /etc/passwd:bob:x:1001:1001:,,,:/home/bob:/bin/bash			a password is set
    /etc/shadow:bob:$6$f9YcHiE8Fc5Ho4Z4bALVuc/:18535:0:99999:7:::	the encrypted password
    bob P 09/30/2020 0 99999 7 -1
    chage -l bob
    Last password change                                    : Sep 30, 2020
    Password expires                                        : never
    Password inactive                                       : never
    Account expires                                         : never
    Minimum number of days between password change          : 0
    Maximum number of days between password change          : 99999
    Number of days of warning before password expires       : 7
  3. lock the password with passwd :
    passwd: password expiry information changed.
    grep bob /etc/{passwd,shadow}
    /etc/passwd:bob:x:1001:1001:,,,:/home/bob:/bin/bash
    /etc/shadow:bob:!$6$f9YcHiE8Fc5Hxdvk$YW1TwjbGerIKvp8vY.rRPBESiIduTOI8.eDzTWjQZyhPMTd6SMl2Ju21dDvEJLTFjeru2YEaWa7o4Z4bALVuc/:18535:0:99999:7:::
    bob L 09/30/2020 0 99999 7 -1
    chage -l bob
    (same as above)
  4. lock the password with passwd :
    passwd: password expiry information changed.
    grep bob /etc/{passwd,shadow}
    /etc/passwd:bob:x:1001:1001:,,,:/home/bob:/bin/bash
    /etc/shadow:bob:$6$f9YcHiE8Fc5Hxdvk$YW1TwjbGerIKvp8vY.rRPBESiIduTOI8.eDzTWjQZyhPMTd6SMl2Ju21dDvEJLTFjeru2YEaWa7o4Z4bALVuc/:18535:0:99999:7:::
    bob P 09/30/2020 0 99999 7 -1
    chage -l bob
    (same as above)
  5. expire the account with usermod :
    (returns nothing)
    bob P 09/30/2020 0 99999 7 -1
    chage -l bob
    Last password change                                    : Sep 30, 2020
    Password expires                                        : never
    Password inactive                                       : never
    Account expires                                         : Jan 02, 1970
    Minimum number of days between password change          : 0
    Maximum number of days between password change          : 99999
    Number of days of warning before password expires       : 7
  6. un-expire the account with usermod :
    (returns nothing)
    bob P 09/30/2020 0 99999 7 -1
    chage -l bob
    Last password change                                    : Sep 30, 2020
    Password expires                                        : never
    Password inactive                                       : never
    Account expires                                         : never
    Minimum number of days between password change          : 0
    Maximum number of days between password change          : 99999
    Number of days of warning before password expires       : 7
  7. expire the account with chage :
    chage -E 1 bob
    (returns nothing)
    bob P 09/30/2020 0 99999 7 -1
    chage -l bob
    Last password change                                    : Sep 30, 2020
    Password expires                                        : never
    Password inactive                                       : never
    Account expires                                         : Jan 02, 1970
    Minimum number of days between password change          : 0
    Maximum number of days between password change          : 99999
    Number of days of warning before password expires       : 7
  8. un-expire the account with chage :
    chage -E -1 bob
    (returns nothing)
    bob P 09/30/2020 0 99999 7 -1
    chage -l bob
    Last password change                                    : Sep 30, 2020
    Password expires                                        : never
    Password inactive                                       : never
    Account expires                                         : never
    Minimum number of days between password change          : 0
    Maximum number of days between password change          : 99999
    Number of days of warning before password expires       : 7
  9. delete the user account :
    userdel -r bob

To "unexpire" a password (source) :

chage stuart
Changing the aging information for stuart
Enter the new value, or press ENTER for the default

	Minimum Password Age [0]: 
	Maximum Password Age [99999]: 
	Last Password Change (YYYY-MM-DD) [2018-06-08]: 
	Password Expiration Warning [7]: 
	Password Inactive [-1]: 
	Account Expiration Date (YYYY-MM-DD) [1970-01-02]: -1
mail

chpasswd

Usage

update passwords non-interactively

Example

echo bob:password | chpasswd
mail

cd

Usage

change directory, i.e. move into another directory

cd has some default behaviors :

Command ... Is interpreted as ... Comments
cd cd $HOME
cd - cd "$OLDPWD" && pwd If you don't want the original directory name to be displayed, use cd "$OLDPWD" instead of cd -
mail

comm

Usage

comm [options] file1 file2

To find lines common to 2 files :
  1. sort file contents
  2. remove duplicates
  3. comm -12 file1 file2

Flags

Flag Usage
-1 suppress column 1, i.e. display lines unique to file2 and common lines
-2 suppress column 2, i.e. display lines unique to file1 and common lines
-3 suppress column 3, i.e. display lines unique to file1 and lines unique to file2 (i.e. hide common lines)

Example

Trying all -1, -2 and -3 options at once :

tmpFile1=$(mktemp); tmpFile2=$(mktemp); echo 'FILE1' > "$tmpFile1"; echo 'FILE2' > "$tmpFile2"; for i in {1..3}; do echo "line $i" >> "$tmpFile1"; done; for i in {3..5}; do echo "line $i" >> "$tmpFile2"; done; cat "$tmpFile1" "$tmpFile2"; for mode in 1 2 3 12; do echo -e "\n'-$mode' mode :"; comm -$mode "$tmpFile1" "$tmpFile2"; done; rm "$tmpFile1" "$tmpFile2"

FILE1			result of cat file1 file2
line 1
line 2
line 3
FILE2
line 3
line 4
line 5

'-1' mode :
FILE2
	line 3		this line is common to both files, others are unique to file2
line 4
line 5

'-2' mode :
FILE1
line 1
line 2
	line 3		this line is common to both files, others are unique to file1

'-3' mode :		common lines are hidden
FILE1
	FILE2
line 1
line 2
	line 4
	line 5

'-12' mode :		displaying only common lines
line 3
mail

cruft

Usage

Cruft is a Debianoid tool to look over your system : It is available as package cruft in the Debian archive.

Flags

Flag Usage
-r reportFile Output report to reportFile instead of standard output.
this option is recommended since output can be VERY verbose
mail

chmod

Usage

change file mode bits (i.e. permissions)

Privileges required to run chmod :

chmod can only be executed by (source) :

chmod has the X flag for setting the executable bit only on directories :

mkdir dir; touch file; ls -l
drwx------ 2 bob developers 4096 Mar 23 16:35 dir
-rw------- 1 bob developers    0 Mar 23 16:35 file
chmod a+X *; ls -l
drwx--x--x 2 bob developers 4096 Mar 23 16:35 dir
-rw------- 1 bob developers    0 Mar 23 16:35 file

Different ways to specify file permissions :

Flags

Flag Usage
-R --recursive change files and directories recursively
--reference=referenceFile apply permissions like those of referenceFile (see also chown's --reference)

Example

testFile=$(mktemp --tmpdir playingWithFilePermissions.XXXXXXXX); ls -l "$testFile"; chmod o=wr "$testFile"; ls -l "$testFile"; chmod o-w+x "$testFile"; ls -l "$testFile"; chmod 777 "$testFile"; ls -l "$testFile"; chmod g=--- "$testFile"; ls -l "$testFile"; rm "$testFile"

-rw------- 1 stuart users 0 Mar	8 16:41 /tmp/playingWithFilePermissions.50YC1hqb		default permissions for new file
-rw----rw- 1 stuart users 0 Mar	8 16:41 /tmp/playingWithFilePermissions.50YC1hqb		made by chmod o=rw
-rw----r-x 1 stuart users 0 Mar	8 16:41 /tmp/playingWithFilePermissions.50YC1hqb		made by chmod o-w+x
-rwxrwxrwx 1 stuart users 0 Mar	8 16:41 /tmp/playingWithFilePermissions.50YC1hqb		made by chmod 777
-rwx---rwx 1 stuart users 0 Mar	8 16:41 /tmp/playingWithFilePermissions.50YC1hqb		made by chmod g=---
mail

chroot

Usage

run command or interactive shell with special root directory "/". Once done, leave with exit.

This command allow many hacks. One of them is changing a user's password while running a machine in "rescue" mode.
In such mode, after the machine has been rebooted via a "Live CD" (or anything similar), its "/" filesystem is mounted as /mnt/something. There are situations where you need to change a user (or root) password, then boot the server normally and log in (with password, since SSH keys are not available...) to investigate.

To do so (as root in rescue mode) :
  1. chroot /mnt/something
  2. passwd
  3. reboot in normal mode
  4. log in as root with the password you've just set
  5. debug / fix what needs to be debugged / fixed
  6. don't forget to restore the root account to its initial state, or at least to lock it.
mail

cryptsetup

Usage

Setup cryptographic volumes for dm-crypt

Flags

Flag Usage
-c cipher --cipher cipher Use the cipher encryption algorithm
-h hashingAlgorithm --hash hashingAlgorithm use hashingAlgorithm for passphrase hashing
-s numBits --key-size numBits use a numBits bits long key

Example

cryptsetup luksFormat
set up a new dm-crypt device in LUKS encryption mode
cryptsetup luksOpen
open an existing dm-crypt device
cryptsetup luksClose
close a dm-crypt device
cryptsetup benchmark
# Tests are approximate using memory only (no storage IO).
PBKDF2-sha1       753287 iterations per second
PBKDF2-sha256     407055 iterations per second
PBKDF2-sha512     324435 iterations per second
PBKDF2-ripemd160  512000 iterations per second
PBKDF2-whirlpool  158299 iterations per second
#  Algorithm | Key |  Encryption |  Decryption
     aes-cbc   128b   167.4 MiB/s   187.6 MiB/s
 serpent-cbc   128b    74.9 MiB/s   213.3 MiB/s
 twofish-cbc   128b   179.5 MiB/s   236.5 MiB/s
     aes-cbc   256b   129.2 MiB/s   141.6 MiB/s
 serpent-cbc   256b    85.6 MiB/s   215.2 MiB/s
 twofish-cbc   256b   185.8 MiB/s   233.7 MiB/s
     aes-xts   256b   175.6 MiB/s   182.9 MiB/s
 serpent-xts   256b   196.6 MiB/s   199.1 MiB/s
 twofish-xts   256b   216.0 MiB/s   215.0 MiB/s
     aes-xts   512b   134.8 MiB/s   136.1 MiB/s
 serpent-xts   512b   195.7 MiB/s   199.9 MiB/s
 twofish-xts   512b   216.5 MiB/s   214.0 MiB/s

http://security.stackexchange.com/questions/40208/recommended-options-for-luks-cryptsetup
	For actual encryption, you will want XTS, which has been designed to support disk encryption efficiently.

http://security.stackexchange.com/questions/5158/for-luks-the-most-preferable-and-safest-cipher
	- In terms of the cipher alone, Serpent is generally agreed upon to be the most secure common cipher for LUKS.
	- (...) assuming you don't have national secrets or sensitive corporate data on your PC, AES-XTS-PLAIN is expected to be resistant for a reasonable timeframe against an attacker.

	==> serpent-xts-256 ?


https://gitlab.com/cryptsetup/cryptsetup/wikis/FrequentlyAskedQuestions
mail

cat

Usage

man cat says concatenate files and print on the standard output. This utility actually has more usages :
  1. effectively concatenate files : cat file1 file2 file3 > resultFile
  2. quickly display the contents of a single file : cat someFile
    this proves useful only when someFile is shorter than the number of lines your terminal can display. Otherwise, you'll only see the yourTerminalHeight trailing lines of someFile. In such case, less, head or tail might be good candidates.

    Please, please, PLEASE, don't fall in the useless-uses-of-cat n00b-trap !

  3. output several lines of text using heredocs
  4. "burn" the contents of an .iso image onto a USB key / storage card to boot from and install a new operating system

Useless use of cat (aka UUOC) :

We ALL did it, but now, the cat | construct should ring the bell of uselessness and waste of resources (even though modern computers have so much CPUs and GB of RAM to waste that such commands will pass unsuspected ).

Actually, any extra | induces an additional process fork, which is an expensive CPU-time operation (especially on loops). Moreover, cat someFile | reads the whole file before piping it to the 2nd command, which delays its execution for big files.

Usage DON'T DO
View the contents of file, which is longer that your terminal height cat file | less less file
View the lines of file matching pattern cat file | grep pattern
cat file | head pattern
cat file | tail pattern
grep pattern file
head pattern file
tail pattern file
Read file line by line cat file | while read line; do echo $line; done while read line; do echo $line; done < file
Alter the lines of file matching pattern cat file | awk '/pattern/ {doSomething}'
cat file | sed 'sed' options
awk '/pattern/ {doSomething}' file
sed 'sed' options file
Extract a field (i.e. a column) from file cat file | cut 'cut' options cut 'cut' options file

Flags

Flag Usage
-n --number number all output lines
mail

cp

Usage

Copy files and directories

Flags

Flag Usage
-a --archive same as -dR --preserve=all
=	-d					-R	--preserve=all
=	--no-dereference --preserve=links	-R	--preserve=all
=	--no-dereference -R --preserve=all
To copy the full contents of a directory, as is, into another :
cp -av sourceDir/* destinationDir
--backup[=backupOption] Instead of overwriting the destination file, make it a "backup" copy. The behavior depends on the value of backupOption :
  • (none) : make simple backups (i.e. only 1 backup, with either the default or the specified suffix)
    -b is equivalent to --backup with no backupOption
  • none, off : never make backups
  • numbered, t : make numbered backups. Will create 1 new backup every time, with incrementing suffix : .~1~, .~2~, ...
  • ...
see examples
-d same as --no-dereference --preserve=links
-f --force (details)
-P --no-dereference never follow symbolic links in sourceDir (i.e. copy the link, not its target)
-p --preserve preserve default attributes
--preserve=attributeList preserve the attributes specified with attributeList :
  • default attributes : mode, ownership, timestamps
  • additional attributes : context, links, xattr, all
-R -r --recursive copy directories recursively
-S suffix --suffix=suffix set the backup suffix (default : ~). works only with simple backups see examples
-s --symbolic-link make a symbolic link instead of copying. These commands are equivalent :
  • cp -s regularFile resultingSymlink
  • ln -s regularFile resultingSymlink
-v --verbose explain what is being done

More about cp -f :

man cp says : if an existing destination file cannot be opened, remove it and try again (this option is ignored when the -n option is also used)
The final part (between parenthesis) is clear (-n disables -f), so let's concentrate on the beginning :

if an existing destination file cannot be opened, remove it and try again

man cp says : If a file descriptor for a destination file cannot be obtained, attempt to unlink the destination file and proceed. It also gives the detailed procedure :

  • when sourceFile is a regular file
  • and when destinationFile exists
  • if a file descriptor for destinationFile can be obtained via actions such as open() (i.e. if destinationFile is writable by the current user)
    • THEN copy sourceFile into destinationFile
    • OTHERWISE delete destinationFile (if enough privileges to do so), then copy sourceFile as destinationFile

Check it :
touch file1; echo -e '\nRound 1'; cp file1 file2; echo -e '\nRound 2'; cp file1 file2; echo -e '\nRound 3'; chmod 200 file2; cp file1 file2; echo -e '\nRound 4a'; chmod 400 file2; cp file1 file2; echo -e '\nRound 4b'; cp -f file1 file2; echo -e '\nRound 5a'; chmod 000 file2; cp file1 file2; echo -e '\nRound 5b'; cp -f file1 file2; rm file[12]
Round 1		file2 didn't exist already, so that was easy !

Round 2		Piece of cake !!!

Round 3		w bit is set, no need to force

Round 4a
cp: cannot create regular file 'file2': Permission denied

Round 4b	w bit is NOT set, -f required

Round 5a
cp: cannot create regular file 'file2': Permission denied

Round 5b	no permission bit is set, -f required

Now if I try with file2 being a file I don't own, and on which I only have read permission (r--) :

cp file1 file2; cp -f file1 file2
cp: cannot create regular file 'file2': Permission denied
cp: cannot remove 'file2': Operation not permitted

As a conclusion, the -f / --force cp flag only serves to overwrite my own files if I have denied myself write access on them.

More about --backup and suffix :

Make a backup of an existing destination :
touch myFile; cp myFile myFile_COPY; cp -b myFile myFile_COPY; ls -1; rm myFile*
myFile
myFile_COPY
myFile_COPY~
The default options do not overwrite the backup :
echo initial > myFile; cp myFile myFile_COPY; cp -b myFile myFile_COPY; echo modified > myFile; cp -b myFile myFile_COPY; ls -1; cat myFile myFile_COPY myFile_COPY~; rm myFile*
myFile
myFile_COPY
myFile_COPY~
modified
modified
initial		contents of myFile_COPY~
Make numbered backups :
echo 'initial version' > myFile; cp --backup=numbered myFile myFile_COPY; for i in {1..5}; do echo "edit $i" > myFile; cp --backup=numbered myFile myFile_COPY; done; for i in myFile*; do echo -en "$i :|"; cat "$i"; done | column -s '|' -t; rm myFile*
myFile :           edit 5
myFile_COPY :      edit 5
myFile_COPY.~1~ :  initial version
myFile_COPY.~2~ :  edit 1
myFile_COPY.~3~ :  edit 2
myFile_COPY.~4~ :  edit 3
myFile_COPY.~5~ :  edit 4
Make suffixed backups :
touch myFile; cp myFile myFile_COPY; cp -b --suffix='_OLD' myFile myFile_COPY; ls -1; rm myFile*
myFile
myFile_COPY
myFile_COPY_OLD
mail

continue

Usage

continue n

Example

Basic example : interrupting a single for loop :

#!/usr/bin/env bash

for i in {1..2}; do
	echo $i
	continue
	echo 'this will never be executed'
done
displays :
1
2

2 nested for loops :

#!/usr/bin/env bash

for i in {1..2}; do
	for j in {a..b}; do
		echo $i$j
		continue
		echo 'this will never be executed'
	done
done
displays :
1a
1b
2a
2b

2 nested for loops and continue 2 :

#!/usr/bin/env bash

for i in {1..2}; do
	for j in {a..b}; do
		echo $i$j
		continue 2
		echo 'this will never be executed'
	done
done
displays :
1a
2a
mail

column

Usage

Display data as columns

Flags

Flag Usage
-c n Use up to n characters-wide screen space to display data (get a terminal window's width and height)
-s char -t Consider char as the column separator in the input, then display data as columns
-t Determine the number of columns the input contains and create a table. Columns are delimited with whitespace, by default, or with the characters supplied with -s.

Example

for i in {1..3}; do echo col1_$i col2_$i; done | column -c 40
col1_1 col2_1	col1_3 col2_3
col1_2 col2_2
for i in {1..3}; do echo col1_$i col2_$i; done | column -t
col1_1	col2_1
col1_2	col2_2
col1_3	col2_3
for i in {1..3}; do echo col1_$i col2_$i; done | column -s 'l' -t
co	1_1 co	2_1
co	1_2 co	2_2
co	1_3 co	2_3
mail

crontab

Table of contents

Usage

crontab is used to :

  • submit jobs definition files to cron
  • list the contents of a cron table (personal or different user)
crontab option Description
-e edit the crontab with EDITOR
-l list registered jobs (view the crontab)
-r remove the crontab
-u kevin work on kevin's crontab
crontab fileName register filename as the new crontab

Unless explicitly specified with -u, all crontab commands apply to the current user.

crontab works so that you cannot append a new job at the end of a table. Instead, you have to :

  1. extract the whole content of the table into a file :
    • for the current user : crontab -l > /tmp/crontab
    • as root, for the user bob : crontab -l -u bob > /tmp/crontab.bob
    You can also launch edition with vi (default) or your favorite editor at the same time with the -e option. If no crontab is available, just create a new text file and go to the next step.
  2. edit the file to add/modify/delete jobs with your favorite text editor. The file MUST end with a blank line.
  3. register the new crontab :
    • for the current user : crontab /tmp/crontab
    • as root, for the user bob : crontab -u bob /tmp/crontab.bob
    This overwrites the previous crontab.
  • On Debianoids, failed CRON tasks are usually logged in (details) :
    • /var/log/syslog
    • /var/log/cron
    • /var/log/messages
  • Looks like there's no concern about them appearing all uppercase in the log files : /USR/SBIN/CRON

crontab time specification (source : man 5 crontab) :

fields :

# usage range of values
1 minutes 0-59
2 hours 0-23
3 day of month 1-31
4 month
  • 1-12
  • jan, feb, mar, apr,
5 day of week
  • 0-6 (Sunday=0 or 7)
  • sun, mon, tue, wed, thu, fri, sat
  • when specifying the day of month AND the day of week, both values are logically OR'd :
    • the expression matches when any is true
    • if both are true, the command is executed only once
  • in some web-based applications (such as Rundeck), you may encounter time specifications for scheduled tasks with up to 7 fields, like : 0 0 23 ? * * *
    • even though they may be described as crontab jobs, these must be understood as scheduled jobs
    • their format —which is NOT the official crontab format— extends it with :
    • this format was popularized by Quartz, which is the reference scheduler in the JVM business

wildcards :

character usage example (more examples below)
*
  • means all values
  • is actually an alias of first-last
* * * * * : run every minute of every hour of every day (very common but rarely a good idea IMHO)
, list of values 0 10,12,16 * * * : run at 10:00, noon and 16:00
- inclusive range of values
  • 30 11-13 * * * : run at 11:30, 12:30 and 13:30
  • 0 0-4,7-9 * * * : run at 0:00, 1:00, 2:00, 3:00, 4:00 and 7:00, 8:00, 9:00
/n do every n intervals
  • */15 * * * * : run every 15 minutes
  • 0 0–23/2 * * * is equivalent to 0 0,2,4,6,8,10,12,14,16,18,20,22 * * *

aliases (source) :

Instead of the first five fields, one of eight special strings may appear :
string meaning
@reboot Run once, at startup.
@yearly
@annually
Run once a year : 0 0 1 1 *
@monthly Run once a month : 0 0 1 * *
@weekly Run once a week : 0 0 * * 0
@daily
@midnight
Run once a day : 0 0 * * *
@hourly Run once an hour : 0 * * * *
  • as for @reboot, the startup time is the time when the cron daemon itself started. Due to the boot order sequence of the machine, this _may_ be before some other system daemons (details)
  • (possibly obsolete) When are they executed ?

Where are actually stored the crontabs ?

  • /etc/cron.d/*
  • /etc/cron.daily
  • /etc/cron.hourly
  • /etc/cron.monthly
  • /etc/cron.weekly
  • /etc/crontab
  • /etc/default/cron
  • /var/spool/cron/crontabs/kevin (Debianoids only)

Error management

With the exception of certain errors in the time fields, errors are not reported until CRON runs the command. All error messages and output are mailed to the crontab owner (or to any address specified with MAILTO=bob@example.com), unless they are silenced by redirecting stdout and stderr to /dev/null with >/dev/null 2>&1.

Even though completely silencing stdout and stderr by sending them to /dev/null looks tempting, this may not be a wise idea. If tasks generate too much jabber, you'd better fix your scripts or run tasks less frequently.

Output is mailed to the user because there is no real terminal on which the cronjobs are being executed. Therefore, there is no screen to display the errors. Also, there is no keyboard to accept input. Does that mean you cannot give input to a CRON job? No. Think back to the discussion on shell scripts. We can redefine stdin, stdout and stderr. This way they can all point to files and behave as we expect.

Keep in mind that CRON is not exact. It synchronizes itself to the top of each minute. On a busy system in which you lose clock ticks, jobs may not be executed until a couple minutes after the scheduled time. In addition, there may be other processes with higher priorities that delay CRON jobs. In some cases, (particularly on very busy systems) jobs might end up being skipped if they are run every minute.

Did CRON job finish ok ? See logs :

  • /var/log/cron
  • /var/log/cronexecutionDate

View all users' crontabs :

  • for user in $(cut -d : -f1 /etc/passwd); do echo $user"'s CRONTAB :"; crontab -l -u $user; done | less
  • or, as root : less /var/spool/cron/crontabs/*

    /var/spool/cron/crontabs/* files are not intended to be edited directly. Use the crontab utility to edit CRON jobs.

Example

Using wildcards :

Let's say we wanted to run a command not at 10 minutes after the hour, but every ten minutes. We could make an entry that looked like this :
0,10,20,30,40,50	*	1,16	*	1-5	/usr/local/bin/command
This runs every 10 minutes: at the top of the hour, 10 minutes after, 20 minutes after, and so on. To make life easier, we could simply create the entry like this :
*/10	*	1,16	*	1-5	/usr/local/bin/command
The /n says that within the specific interval (in this case, every minute), run the command every n minutes; in this case, every 10 minutes.
We can also use this even when we specify a range. For example, if the job was only supposed to run between 20 minutes after the hour and 40 minutes after the hour, the entry might look like this :
20-40	*	1,16	*	1-5	/usr/local/bin/command
What if you wanted it to run at these times, but only every three minutes? The line might look like this :
20-40/3	*	1,16	*	1-5	/usr/local/bin/command
To make things even more complicated, you could say that you wanted the command to run every two minutes between the hour and 20 minutes after, every three minutes between 20 and 40 minutes after, then every 5 minutes between 40 minutes after and the hour :
0-20/2,21-40/3,41-59/5	*	1,16	*	1-5	/usr/local/bin/command
To make the fun last longer, let's imagine you have 2 jobs you want to execute every 2 minutes (source) :
  • jobEven on even minutes : 2, 4, 6, ..., 58, 00
  • jobOdd on odd minutes : 1, 3, 5, ..., 59
*/2	*	*	*	*	jobEven
1-59/2	*	*	*	*	jobOdd

And what if I want a job to run every n minutes with jobExecutionMinute % n != 0 ? (source)

Instead of :

1,6,11,16,21,26,31,36,41,46,51,56 * * * * /my/script
3,13,23,33,43,53 * * * * /my/other/script
you can do :
1-56/5 * * * * /my/script
3-53/10 * * * * /my/other/script

Remember :
  • Syntax : start-stop/increment
  • Ranges are inclusive : start and stop values are part of the range.

Monthly reboot :

# 1st monday of month at 6h30
30 6 * * 1 [ $(/bin/date +\%d) -lt 8 ] && /sbin/init 6

# Last wednesday of every month, at 6h30
#30 6 * * 3 [[ $(date +\%d) == $(echo "$(echo "$(cal -s )"|awk '{print $4}')"|tail -1) ]] && /sbin/init 6

# not tested yet
			
mail

chown

Flags

Flag Usage
-h --no-dereference Affect symlink instead of changing owner/group of its target
-R --recursive operate on files and directories recursively
--reference=referenceFile change owner + group like those of referenceFile (see also chmod's --reference)

Example

Command New user owner New group owner
chown bob myFile bob (unchanged)
chown bob:developers myFile bob developers
chown bob: myFile bob bob's login group
chown :developers myFile (unchanged) developers (equivalent to chgrp)
mail

chkconfig

Usage

chkconfig has been obsoleted by systemd and systemctl.

Flags

Flag Usage
--add serviceName add a new service for management
--del serviceName Unregister serviceName from chkconfig service management
--list
--list serviceName
List all the registered daemons and their runlevel activation status
List the runlevel activation status for serviceName only.
-s daemon on|off [level]
--set
Set the specified daemon ON or OFF for the specified runlevel. If no level is specified, the on/off is applied to ALL runlevels (?).
ex : chkconfig -s smb on

Example

List daemons with ON/OFF status for each runlevel :

  • chkconfig --list
  • chkconfig --list httpd

Enable / disable daemon on given runlevels :

These commands enable / disable daemons, but they don't start / stop them.

  • chkconfig --level 345 nscd off
  • chkconfig --level 3 httpd on

If no runlevel is specified, then all the possible runlevels are impacted :

chkconfig iptables off
(nothing)
chkconfig --list iptables
iptables	0:off	1:off	2:off	3:off	4:off	5:off	6:off
chkconfig iptables on
(nothing)
chkconfig --list iptables
iptables	0:off	1:off	2:on	3:on	4:on	5:on	6:off

Query a daemon activation status :

chkconfig iptables returns a Unix success / failure if iptables is enabled / disabled in the current runlevel :
chkconfig iptables off; chkconfig iptables; echo $?; chkconfig iptables on; chkconfig iptables; echo $?
1
0

When chkconfig complains error reading info for serviceName :

This happens :
  • when listing services : chkconfig --list 2>&1 | less
  • when taking actions on serviceName : chkconfig --del serviceName

In my case, this was caused by a broken link :

/etc/init.d/serviceName -> /installDir/serviceName/bin/scripts/serviceName.sh
Solution : fix this symlink (delete it if applicable, change target when possible)

How to specify runlevels and start/stop priority from within /etc/init.d/scriptName :

  1. add 2 commented lines in the header of scriptName :
    # chkconfig: runlevels startPriority stopPriority
    # description: description
    • runlevels : list of runlevels on which this script should start by default. To mean "none", just indicate -.
    • startPriority : (explicit)
    • stopPriority : (explicit)
    • description : (explicit) This can span on multiple lines with a trailing \ on each continued line.
  2. copy the script as /etc/init.d/scriptName
  3. register this new script : chkconfig --add scriptName
    This will create the appropriate symlinks :
    • /etc/rc.d/rcrunlevel.d/KstopPriorityscriptName -> ../init.d/scriptName
    • /etc/rc.d/rcrunlevel.d/SstartPriorityscriptName -> ../init.d/scriptName
mail

chattr

Usage

change file attributes. These attributes can be :

Flags

Flag Usage
-d target is a directory, not a regular file.

Example

Don't forget that the i flag requires root privileges.
Set a file immutable :
chattr +i myFile
Remove the immutable flag from a file :
chattr -i myFile
Set a directory immutable :
chattr -d +i myDirectory
Remove the immutable flag from a directory :
chattr -d -i myDirectory
mail

cut

Usage

cut [options] file

Read file (or stdin if file is "-") line by line and display only the selected bytes, characters or fields.

Flags

Flag Usage
-b n display the nth byte
specify numeric arguments
-c n display the nth character
  • even though the manual is about characters, this flag actually selects bytes (1 character = 1 byte for ASCII strings only) :
    for myString in 'aeiouy' 'àèìòùy'; do echo "$myString" | cut -c 2-5; done
    eiou
    �è�	this is the 2nd byte of the à, then the è, then the 1st byte of the ì
  • specify numeric arguments, examples
-d character use character as field delimiter, defaults to TAB
-f n display the nth field
specify numeric arguments
--output-delimiter=string use string as the output delimiter. Defaults to the input delimiter, i.e. the value of -d

Numeric arguments for -b, -c and -f :

These apply to byte, character or field, depending on which flag is used.
  • n : nth, counted from 1
  • n- : from nth to end of line
  • n-m : from nth to mth (included)
  • -m : from first to mth (included)
  • x,y,z : the xth, the yth and the zth
    the data fields will be displayed following the order they have in the input, not the order you list them

Example

Basic examples

echo 'aze rty uio' | cut -d ' ' -f 2,3
rty uio
echo a,b,c | cut -d ',' -f2,3
b,c
echo a,b,c | cut -d ',' -f2,3 --output-delimiter=' '
b c
for i in {1..26}; do echo {a..z} | cut -d ' ' -f 1-$i; done
a
a b
a b c

a b c d e f g h i j k l m n o p q r s t u v w x y z

Select characters :

echo hello | cut -c 2
e
echo hello | cut -c -2
he
echo hello | cut -c 2-
llo