ksh - Korn Shell
Le Korn Shell (ksh) est un puissant shell Unix développé par David Korn à Bell Labs. En tant que superset du shell Bourne (sh), ksh combine la conformité POSIX avec les fonctionnalités de programmation avancées, ce qui le rend particulièrement populaire dans les environnements d'entreprise et parmi les administrateurs système qui nécessitent des capacités de script robustes. Le shell Korn offre des performances supérieures, une fonctionnalité intégrée étendue et des constructions de programmation sophistiquées tout en maintenant la compatibilité avec les scripts shell traditionnels. Il sert de pont entre la simplicité de POSIX sh et les caractéristiques avancées des coquilles modernes.
Installation et configuration
Coque de Korn Variantes
# Check which ksh variant is installed
echo $KSH_VERSION
# Output examples:
# Version AJM 93u+ 2012-08-01 (ksh93)
# Version JM 93t+ 2010-03-05 (ksh93)
# Common ksh implementations
which ksh # System ksh
which ksh93 # AT&T ksh93
which mksh # MirBSD Korn Shell
which pdksh # Public Domain Korn Shell
# Check shell features
print $(.sh.version) 2>/dev/null||echo "Not ksh93"
Installation de Korn Coque
# Ubuntu/Debian
sudo apt update && sudo apt install ksh
# For ksh93 specifically
sudo apt install ksh93
# CentOS/RHEL/Fedora
sudo dnf install ksh
# macOS (using Homebrew)
brew install ksh93
# Arch Linux
sudo pacman -S ksh
# FreeBSD
pkg install ksh93
# From source (ksh93)
git clone https://github.com/att/ast.git
cd ast
bin/package make
```_
### Définir ksh comme Shell par défaut
```bash
# Check ksh installation
which ksh
/bin/ksh
# Add ksh to available shells
echo /bin/ksh|sudo tee -a /etc/shells
# Set ksh as default shell
chsh -s /bin/ksh
# Verify change (restart terminal)
echo $SHELL
/bin/ksh
# Check ksh version and features
echo $KSH_VERSION
set|grep KSH
```_
### Configuration de base
```bash
# Create .kshrc for interactive shell configuration
cat > ~/.kshrc ``<< 'EOF'
# Korn Shell configuration
# Set environment variables
export EDITOR=vi
export PAGER=less
export HISTSIZE=1000
# Set prompt
PS1='$\\\{USER\\\}@$\\\{HOSTNAME\\\}:$\\\{PWD\\\}$ '
# Aliases
alias ll='ls -l'
alias la='ls -la'
alias h='history'
# Enable vi editing mode
set -o vi
# History options
set -o trackall
EOF
# Set ENV variable to load .kshrc
export ENV=~/.kshrc
echo 'export ENV=~/.kshrc' >``> ~/.profile
Ksh-Specific Caractéristiques et syntaxe
Types de variables et déclarations
# Integer variables
typeset -i num=10
integer count=0
count+=5 # count is now 5
# Floating point variables (ksh93)
typeset -F2 price=19.99 # 2 decimal places
float temperature=98.6
# Array variables
typeset -a fruits
fruits=(apple banana orange)
set -A colors red green blue # Alternative syntax
# Associative arrays (ksh93)
typeset -A config
config[host]=localhost
config[port]=8080
# Read-only variables
typeset -r CONSTANT="unchangeable"
readonly PI=3.14159
# Exported variables
typeset -x PATH="/usr/local/bin:$PATH"
export LANG=en_US.UTF-8
Extension avancée des paramètres
# String manipulation
string="Hello, World!"
print $\\\\{#string\\\\} # Length: 13
print $\\\\{string#Hello\\\\} # Remove from beginning: , World!
print $\\\\{string%World!\\\\} # Remove from end: Hello,
print $\\\\{string/Hello/Hi\\\\} # Replace first: Hi, World!
print $\\\\{string//l/L\\\\} # Replace all: HeLLo, WorLd!
# Case conversion (ksh93)
print $\\\\{string^^\\\\} # Uppercase: HELLO, WORLD!
print $\\\\{string,,\\\\} # Lowercase: hello, world!
print $\\\\{string^\\\\} # Capitalize first: Hello, world!
# Substring extraction
print $\\\\{string:0:5\\\\} # First 5 characters: Hello
print $\\\\{string:7\\\\} # From position 7: World!
print $\\\\{string:(-6)\\\\} # Last 6 characters: World!
# Default values
print $\\\\{undefined:-"default"\\\\} # Use default if undefined
print $\\\\{undefined:="default"\\\\} # Set default if undefined
print $\\\\{defined:+"alternate"\\\\} # Use alternate if defined
Tableaux et tableaux associatifs
# Indexed arrays
typeset -a numbers
numbers=(1 2 3 4 5)
numbers[10]=100 # Sparse array
# Array operations
print $\\\\{numbers[0]\\\\} # First element
print $\\\\{numbers[@]\\\\} # All elements
print $\\\\{#numbers[@]\\\\} # Number of elements
print $\\\\{!numbers[@]\\\\} # All indices
# Array assignment
numbers+=(6 7 8) # Append elements
unset numbers[2] # Remove element
# Associative arrays (ksh93)
typeset -A person
person[name]="John Doe"
person[age]=30
person[city]="New York"
# Iterate over associative array
for key in "$\\\\{!person[@]\\\\}"; do
print "$key: $\\\\{person[$key]\\\\}"
done
# Multi-dimensional arrays (ksh93)
typeset -A matrix
matrix[1,1]=a
matrix[1,2]=b
matrix[2,1]=c
matrix[2,2]=d
Opérations arithmétiques et mathématiques
# Arithmetic expansion
result=$((5 + 3 * 2)) # 11
result=$((2 ** 8)) # 256 (exponentiation)
# Arithmetic with variables
typeset -i x=10 y=3
result=$((x / y)) # Integer division: 3
remainder=$((x % y)) # Modulo: 1
# Floating point arithmetic (ksh93)
typeset -F result
result=$((10.0 / 3.0)) # 3.333333
# Mathematical functions (ksh93)
result=$((sin(3.14159/2))) # Sine function
result=$((sqrt(16))) # Square root
result=$((log(10))) # Natural logarithm
result=$((exp(2))) # Exponential function
# Increment and decrement
((x++)) # Post-increment
((++x)) # Pre-increment
((x--)) # Post-decrement
((--x)) # Pre-decrement
((x += 5)) # Add and assign
E/S avancé et réorientation
# Co-processes
print -p "command" # Send to co-process
read -p response # Read from co-process
# File descriptors
exec 3< input.txt # Open file for reading
exec 4> output.txt # Open file for writing
read line <&3 # Read from fd 3
print "data" >&4 # Write to fd 4
exec 3<&- # Close fd 3
exec 4>&- # Close fd 4
# Here strings
command <<< "input string"
# Process substitution (ksh93)
diff <(sort file1) <(sort file2)
command > >(process_output)
# Network I/O (ksh93)
exec 5<>/dev/tcp/hostname/port
print -u5 "GET / HTTP/1.0\n"
read -u5 response
Structures de contrôle et contrôle du débit
Énoncés conditionnels améliorés
# [[ ]] conditional (preferred in ksh)
if [[ $string == pattern* ]]; then
print "String starts with pattern"
fi
if [[ $string =~ regex ]]; then
print "String matches regex"
fi
if [[ -f $file && -r $file ]]; then
print "File exists and is readable"
fi
# Pattern matching in conditionals
case $filename in
*.@(txt|doc|pdf))
print "Document file"
;;
*.@(jpg|png|gif))
print "Image file"
;;
*)
print "Unknown file type"
;;
esac
# Numeric comparisons
if (( num > 10 && num ``< 100 )); then
print "Number is between 10 and 100"
fi
Constructions de boucles avancées
# For loops with ranges
for i in \\\{1..10\\\}; do
print "Number: $i"
done
for i in \\\{1..10..2\\\}; do # Step by 2
print "Odd number: $i"
done
# C-style for loops
for ((i=1; i<=10; i++)); do
print "Counter: $i"
done
# For loops with arrays
for element in "$\\\{array[@]\\\}"; do
print "Element: $element"
done
# While loops with advanced conditions
while (( count < limit )); do
print "Count: $count"
((count++))
done
# Until loops
until [[ -f ready.flag ]]; do
print "Waiting for ready flag..."
sleep 2
done
# Select loops for menus
select option in "Option 1" "Option 2" "Option 3" "Quit"; do
case $option in
"Option 1")
print "You selected option 1"
;;
"Option 2")
print "You selected option 2"
;;
"Option 3")
print "You selected option 3"
;;
"Quit")
break
;;
*)
print "Invalid selection"
;;
esac
done
Traitement des exceptions
# Trap signals and errors
cleanup() \\\{
print "Cleaning up..."
rm -f temp_files
exit 1
\\\}
trap cleanup INT TERM EXIT
# Error handling with ERR trap
error_handler() \\\{
print "Error occurred in line $1"
exit 1
\\\}
trap 'error_handler $LINENO' ERR
set -e # Exit on error
# Try-catch equivalent using functions
try() \\\{
"$@"
return $?
\\\}
catch() \\\{
case $? in
0) return 0 ;;
*)
print "Error: $1"
return 1
;;
esac
\\\}
# Usage
if try risky_command; then
print "Command succeeded"
else
catch "Command failed"
fi
Fonctions et programmation avancée
Définition et caractéristiques de la fonction
# Basic function definition
function greet \\\{
print "Hello, $1!"
\\\}
# Alternative syntax
greet() \\\{
print "Hello, $1!"
\\\}
# Function with local variables
function calculate_stats \\\{
typeset -i sum=0 count=0
typeset -F average
for num in "$@"; do
((sum += num))
((count++))
done
if ((count >`` 0)); then
((average = sum / count))
print "Sum: $sum, Count: $count, Average: $average"
fi
\\\\}
# Function with return value
function is_prime \\\\{
typeset -i num=$1 i
if ((num < 2)); then
return 1
fi
for ((i = 2; i * i <= num; i++)); do
if ((num % i == 0)); then
return 1
fi
done
return 0
\\\\}
# Usage
if is_prime 17; then
print "17 is prime"
fi
Fonctions avancées
# Function with named parameters (ksh93)
function process_file \\\\{
typeset file="$1" mode="$\\\\{2:-read\\\\}" verbose="$\\\\{3:-false\\\\}"
[[ $verbose == true ]] && print "Processing $file in $mode mode"
case $mode in
read)
cat "$file"
;;
write)
print "Writing to $file"
;;
*)
print "Unknown mode: $mode" >&2
return 1
;;
esac
\\\\}
# Recursive functions
function factorial \\\\{
typeset -i n=$1
if ((n <= 1)); then
print 1
else
print $((n * $(factorial $((n - 1)))))
fi
\\\\}
# Function with variable number of arguments
function sum_all \\\\{
typeset -i total=0
while (($# > 0)); do
((total += $1))
shift
done
print $total
\\\\}
# Function libraries and namespaces (ksh93)
namespace math \\\\{
function add \\\\{ print $(($1 + $2)); \\\\}
function multiply \\\\{ print $(($1 * $2)); \\\\}
\\\\}
# Usage
result=$(math.add 5 3)
Coprocessus et historique Emploi
# Start co-process
command|&
coproc_pid=$!
# Communicate with co-process
print -p "input data"
read -p response
# Background job management
long_running_command &
job_pid=$!
# Wait for specific job
wait $job_pid
# Job control
jobs # List active jobs
fg %1 # Bring job 1 to foreground
bg %1 # Send job 1 to background
kill %1 # Kill job 1
# Disown jobs
disown %1 # Remove job from job table
Commandes et services publics intégrés
Ksh Commandes intégrées
# print command (preferred over echo)
print "Simple message"
print -n "No newline"
print -r "Raw output (no escape processing)"
print -u2 "Output to stderr"
# printf for formatted output
printf "%s: %d\n" "Count" 42
printf "%-10s %5d\n" "Name" 123
# read with advanced options
read var # Read single variable
read -r line # Raw read (no backslash processing)
read -t 10 input # Read with timeout
read -s password # Silent read (no echo)
read -A array # Read into array
# typeset for variable attributes
typeset -i integer_var=10
typeset -F2 float_var=3.14
typeset -u upper_var="hello" # Uppercase
typeset -l lower_var="HELLO" # Lowercase
typeset -r readonly_var="constant"
# whence command (which equivalent)
whence command # Show command type
whence -v command # Verbose output
whence -a command # Show all matches
Traitement des chaînes
# String comparison and matching
[[ $string == pattern ]] # Pattern matching
[[ $string != pattern ]] # Pattern non-matching
[[ $string < other ]] # Lexicographic comparison
[[ $string > other ]] # Lexicographic comparison
# Pattern matching with extended globs
[[ $filename == *.@(txt|doc) ]] # Match .txt or .doc
[[ $string == +([0-9]) ]] # Match one or more digits
[[ $string == ?([+-])+([0-9]) ]] # Optional sign, required digits
# String manipulation functions (ksh93)
string="Hello, World!"
print $\\\\{string/World/Universe\\\\} # Replace first occurrence
print $\\\\{string//l/L\\\\} # Replace all occurrences
print $\\\\{string#*,\\\\} # Remove up to first comma
print $\\\\{string%,*\\\\} # Remove from last comma
Opérations de fichiers et de répertoires
# File testing
[[ -e file ]] # File exists
[[ -f file ]] # Regular file
[[ -d dir ]] # Directory
[[ -L link ]] # Symbolic link
[[ -r file ]] # Readable
[[ -w file ]] # Writable
[[ -x file ]] # Executable
[[ -s file ]] # Non-empty file
# File comparison
[[ file1 -nt file2 ]] # file1 newer than file2
[[ file1 -ot file2 ]] # file1 older than file2
[[ file1 -ef file2 ]] # Same file (hard links)
# Directory operations
cd directory # Change directory
pushd directory # Push directory onto stack
popd # Pop directory from stack
dirs # Show directory stack
# File globbing with extended patterns
ls *.@(txt|doc) # Files ending in .txt or .doc
ls +([0-9]).txt # Files with numeric names
ls !(*.tmp) # All files except .tmp files
Configuration et personnalisation
Options en matière d'environnement et de coque
# Shell options
set -o vi # Vi editing mode
set -o emacs # Emacs editing mode
set -o trackall # Track all commands for hashing
set -o monitor # Enable job control
set -o notify # Report job status immediately
set -o noglob # Disable filename expansion
set -o noclobber # Prevent output redirection from overwriting
# History options
set -o hist # Enable command history
HISTSIZE=1000 # History size in memory
HISTFILE=~/.ksh_history # History file location
# Prompt customization
PS1='$\\\\{USER\\\\}@$\\\\{HOSTNAME\\\\}:$\\\\{PWD##*/\\\\}$ '
PS2='> ' # Continuation prompt
PS3='#? ' # Select prompt
PS4='+ ' # Debug prompt
# Advanced prompt with functions
function set_prompt \\\\{
typeset git_branch=""
if [[ -d .git ]]; then
git_branch=" ($(git branch --show-current 2>/dev/null))"
fi
PS1="$\\\\{USER\\\\}@$\\\\{HOSTNAME\\\\}:$\\\\{PWD##*/\\\\}$\\\\{git_branch\\\\}$ "
\\\\}
# Set prompt command (ksh93)
PROMPT_COMMAND=set_prompt
Aliases et fonctions
# Simple aliases
alias ll='ls -l'
alias la='ls -la'
alias h='history'
alias ..='cd ..'
alias ...='cd ../..'
# Aliases with parameters (use functions instead)
function mkcd \\\\{
mkdir -p "$1" && cd "$1"
\\\\}
function extract \\\\{
case $1 in
*.tar.gz|*.tgz) tar xzf "$1" ;;
*.tar.bz2|*.tbz2) tar xjf "$1" ;;
*.zip) unzip "$1" ;;
*.rar) unrar x "$1" ;;
*) print "Unknown archive format" ;;
esac
\\\\}
# Conditional aliases
if whence -q vim; then
alias vi=vim
fi
# Platform-specific aliases
case $(uname) in
Linux)
alias ls='ls --color=auto'
;;
Darwin)
alias ls='ls -G'
;;
esac
Achèvement et édition
# Command line editing
set -o vi # Vi editing mode
set -o emacs # Emacs editing mode (default)
# Key bindings (vi mode)
# Esc: Enter command mode
# i: Insert mode
# a: Append mode
# A: Append at end of line
# I: Insert at beginning of line
# dd: Delete line
# yy: Yank (copy) line
# p: Paste
# Key bindings (emacs mode)
# Ctrl+A: Beginning of line
# Ctrl+E: End of line
# Ctrl+K: Kill to end of line
# Ctrl+U: Kill to beginning of line
# Ctrl+W: Kill previous word
# Ctrl+Y: Yank (paste)
# Ctrl+R: Reverse search
# Tab completion (basic)
set -o complete # Enable completion
Performance et optimisation
Caractéristiques de performance
# Built-in commands vs external commands
# Use built-ins when possible for better performance
typeset -i count=0 # Built-in integer arithmetic
((count++)) # Built-in increment
# String operations
string="Hello, World!"
print $\\\\{#string\\\\} # Built-in length
print $\\\\{string%World*\\\\} # Built-in pattern removal
# Array operations
typeset -a array=(1 2 3 4 5)
print $\\\\{#array[@]\\\\} # Built-in array length
# Avoid subshells when possible
# Slow: result=$(command)
# Fast: command|read result (when appropriate)
# Use co-processes for repeated communication
command|&
for data in "$\\\\{input_data[@]\\\\}"; do
print -p "$data"
read -p result
process_result "$result"
done
Gestion de la mémoire
# Unset variables when no longer needed
unset large_array
unset temporary_variable
# Use local variables in functions
function process_data \\\\{
typeset -a local_array
typeset local_var
# Process data with local variables
# Variables are automatically cleaned up
\\\\}
# Limit history size
HISTSIZE=500 # Reasonable history size
Débogue et profilage
# Debug mode
set -x # Print commands as executed
set +x # Disable debug mode
# Verbose mode
set -v # Print input lines as read
set +v # Disable verbose mode
# Function tracing
function trace_function \\\\{
print "Entering function: $\\\\{.sh.fun\\\\}" >&2
print "Arguments: $*" >&2
\\\\}
# Performance timing
function time_function \\\\{
typeset start_time end_time
start_time=$(date +%s%N)
"$@" # Execute command
end_time=$(date +%s%N)
print "Execution time: $(((end_time - start_time) / 1000000)) ms" >&2
\\\\}
# Usage
time_function complex_operation arg1 arg2
Meilleures pratiques et techniques avancées
Structure des scripts
#!/bin/ksh
# Script description
# Author: Your Name
# Date: YYYY-MM-DD
# Strict mode
set -euo pipefail
# Global variables
typeset -r SCRIPT_NAME=$\\\\{0##*/\\\\}
typeset -r SCRIPT_DIR=$\\\\{0%/*\\\\}
typeset -r VERSION="1.0"
# Functions
function usage \\\\{
cat << EOF
Usage: $SCRIPT_NAME [OPTIONS] [ARGUMENTS]
OPTIONS:
-h, --help Show this help
-v, --version Show version
-d, --debug Enable debug mode
EOF
\\\\}
function main \\\\{
# Parse arguments
while (($# > 0)); do
case $1 in
-h|--help)
usage
exit 0
;;
-v|--version)
print "$SCRIPT_NAME version $VERSION"
exit 0
;;
-d|--debug)
set -x
shift
;;
-*)
print "Unknown option: $1" >&2
usage >&2
exit 1
;;
*)
break
;;
esac
done
# Main logic here
print "Script execution completed"
\\\\}
# Error handling
function cleanup \\\\{
# Cleanup code
rm -f temp_files
\\\\}
trap cleanup EXIT
# Run main function
main "$@"
Patterns de manipulation des erreurs
# Robust error handling
function safe_command \\\\{
if ! command "$@"; then
print "Error: Command failed: $*" >&2
return 1
fi
\\\\}
# Input validation
function validate_file \\\\{
typeset file=$1
if [[ ! -f $file ]]; then
print "Error: File '$file' does not exist" >&2
return 1
fi
if [[ ! -r $file ]]; then
print "Error: File '$file' is not readable" >&2
return 1
fi
return 0
\\\\}
# Retry mechanism
function retry_command \\\\{
typeset -i attempts=3 delay=1
typeset command="$*"
for ((i = 1; i <= attempts; i++)); do
if eval "$command"; then
return 0
fi
if ((i < attempts)); then
print "Attempt $i failed, retrying in $delay seconds..." >&2
sleep $delay
((delay *= 2))
fi
done
print "All $attempts attempts failed" >&2
return 1
\\\\}
Considérations en matière de sécurité
# Input sanitization
function sanitize_input \\\\{
typeset input=$1
# Remove dangerous characters
input=$\\\\{input//[;&|`$()]/\\}
# Validate against whitelist
if [[ $input != +([a-zA-Z0-9_.-]) ]]; then
print "Invalid input: $input" >&2
return 1
fi
print "$input"
\\}
# Safe temporary files
function create_temp_file \\{
typeset temp_file
temp_file=$(mktemp)||\\{
print "Failed to create temporary file" >&2
return 1
\\}
# Set restrictive permissions
chmod 600 "$temp_file"
print "$temp_file"
\\}
# Secure PATH
export PATH="/usr/local/bin:/usr/bin:/bin"
# Use full paths for critical commands
/bin/rm -f "$temp_file"
/usr/bin/find "$directory" -name "*.tmp" -delete
Le Korn Shell est un shell puissant et mature qui relie la programmation traditionnelle de shell Unix avec des besoins de script modernes. Sa combinaison de conformité POSIX, de fonctionnalités de programmation avancées et d'excellentes performances le rend particulièrement précieux dans les environnements d'entreprise où la fiabilité et la portabilité sont primordiales. Bien qu'il ne possède pas les vastes écosystèmes plugin des shells modernes comme Zsh, les capacités intégrées de ksh, les fonctions mathématiques et les fonctionnalités de script robustes en font un excellent choix pour l'administration du système, l'automatisation et les tâches de programmation shell complexes.