fifo_demo.sh

Download
bash 321 lines 6.9 KB
  1#!/usr/bin/env bash
  2set -euo pipefail
  3
  4# Named Pipe (FIFO) Demonstrations
  5# Shows how to use named pipes for inter-process communication
  6
  7# Cleanup function
  8cleanup() {
  9    echo
 10    echo "Cleaning up..."
 11    rm -f /tmp/demo_fifo_* /tmp/producer_done
 12    jobs -p | xargs -r kill 2>/dev/null || true
 13}
 14
 15# Set trap for cleanup
 16trap cleanup EXIT INT TERM
 17
 18echo "=== Named Pipe (FIFO) Demonstrations ==="
 19echo
 20
 21# --- Demo 1: Basic FIFO usage ---
 22demo_basic_fifo() {
 23    echo "1. Basic FIFO Usage"
 24    echo "-------------------"
 25
 26    local fifo="/tmp/demo_fifo_basic"
 27
 28    # Create named pipe
 29    mkfifo "$fifo"
 30    echo "Created FIFO: $fifo"
 31
 32    # Producer (background)
 33    {
 34        echo "Producer: Starting..."
 35        for i in {1..5}; do
 36            echo "Message $i"
 37            sleep 0.5
 38        done
 39    } > "$fifo" &
 40
 41    # Consumer (foreground)
 42    echo "Consumer: Reading from FIFO..."
 43    while IFS= read -r line; do
 44        echo "  Received: $line"
 45    done < "$fifo"
 46
 47    echo "Consumer: Done"
 48
 49    rm -f "$fifo"
 50    echo
 51}
 52
 53# --- Demo 2: Producer-Consumer pattern ---
 54demo_producer_consumer() {
 55    echo "2. Producer-Consumer Pattern"
 56    echo "----------------------------"
 57
 58    local fifo="/tmp/demo_fifo_pc"
 59    local done_flag="/tmp/producer_done"
 60
 61    mkfifo "$fifo"
 62    rm -f "$done_flag"
 63
 64    # Producer: Generate data
 65    producer() {
 66        echo "Producer: Generating data..."
 67        for i in {1..10}; do
 68            # Simulate some work
 69            local result=$((i * i))
 70            echo "$i squared is $result"
 71            sleep 0.2
 72        done
 73        echo "DONE"  # Signal completion
 74        touch "$done_flag"
 75    }
 76
 77    # Consumer: Process data
 78    consumer() {
 79        echo "Consumer: Processing data..."
 80        local count=0
 81        while IFS= read -r line; do
 82            if [[ "$line" == "DONE" ]]; then
 83                break
 84            fi
 85            ((count++))
 86            echo "  [$count] Processed: $line"
 87        done
 88        echo "Consumer: Processed $count items"
 89    }
 90
 91    # Start producer in background
 92    producer > "$fifo" &
 93    local producer_pid=$!
 94
 95    # Start consumer in foreground
 96    consumer < "$fifo"
 97
 98    # Wait for producer to finish
 99    wait "$producer_pid"
100
101    rm -f "$fifo" "$done_flag"
102    echo
103}
104
105# --- Demo 3: Bidirectional communication ---
106demo_bidirectional() {
107    echo "3. Bidirectional Communication (Two FIFOs)"
108    echo "------------------------------------------"
109
110    local request_fifo="/tmp/demo_fifo_request"
111    local response_fifo="/tmp/demo_fifo_response"
112
113    mkfifo "$request_fifo"
114    mkfifo "$response_fifo"
115
116    # Server: Responds to requests
117    server() {
118        echo "Server: Starting..."
119        while IFS= read -r request; do
120            if [[ "$request" == "QUIT" ]]; then
121                echo "GOODBYE" > "$response_fifo"
122                break
123            fi
124
125            # Process request (simple echo server with uppercase)
126            local response="${request^^}"
127            echo "Server: Request='$request', Response='$response'"
128            echo "$response" > "$response_fifo"
129        done < "$request_fifo"
130        echo "Server: Shutting down"
131    }
132
133    # Client: Sends requests
134    client() {
135        echo "Client: Connecting..."
136        local -a requests=("hello" "world" "test" "QUIT")
137
138        for req in "${requests[@]}"; do
139            echo "Client: Sending '$req'"
140            echo "$req" > "$request_fifo"
141
142            # Read response
143            IFS= read -r response < "$response_fifo"
144            echo "Client: Got response '$response'"
145            sleep 0.3
146        done
147        echo "Client: Done"
148    }
149
150    # Start server in background
151    server &
152    local server_pid=$!
153
154    # Give server time to start
155    sleep 0.5
156
157    # Run client
158    client
159
160    # Wait for server
161    wait "$server_pid"
162
163    rm -f "$request_fifo" "$response_fifo"
164    echo
165}
166
167# --- Demo 4: Load balancing with multiple workers ---
168demo_load_balancing() {
169    echo "4. Load Balancing with Multiple Workers"
170    echo "----------------------------------------"
171
172    local job_fifo="/tmp/demo_fifo_jobs"
173    mkfifo "$job_fifo"
174
175    # Worker function
176    worker() {
177        local worker_id=$1
178        echo "Worker $worker_id: Started"
179
180        while IFS= read -r job; do
181            if [[ "$job" == "STOP" ]]; then
182                break
183            fi
184
185            # Simulate work
186            echo "  Worker $worker_id: Processing job '$job'"
187            sleep 0.5
188            echo "  Worker $worker_id: Completed job '$job'"
189        done
190
191        echo "Worker $worker_id: Stopped"
192    }
193
194    # Start multiple workers
195    local num_workers=3
196    echo "Starting $num_workers workers..."
197
198    for i in $(seq 1 $num_workers); do
199        worker "$i" < "$job_fifo" &
200    done
201
202    # Give workers time to start
203    sleep 0.5
204
205    # Dispatcher: Send jobs
206    echo
207    echo "Dispatcher: Sending jobs..."
208    {
209        for job_num in {1..6}; do
210            echo "Job-$job_num"
211        done
212
213        # Send stop signal to each worker
214        for i in $(seq 1 $num_workers); do
215            echo "STOP"
216        done
217    } > "$job_fifo"
218
219    # Wait for all workers
220    wait
221
222    rm -f "$job_fifo"
223    echo
224}
225
226# --- Demo 5: Pipeline with FIFO ---
227demo_pipeline() {
228    echo "5. Complex Pipeline with FIFO"
229    echo "-----------------------------"
230
231    local fifo1="/tmp/demo_fifo_pipe1"
232    local fifo2="/tmp/demo_fifo_pipe2"
233
234    mkfifo "$fifo1" "$fifo2"
235
236    # Stage 1: Generate numbers
237    {
238        echo "Stage 1: Generating numbers..."
239        seq 1 10
240    } > "$fifo1" &
241
242    # Stage 2: Square the numbers
243    {
244        echo "Stage 2: Squaring..."
245        while read -r num; do
246            echo $((num * num))
247        done
248    } < "$fifo1" > "$fifo2" &
249
250    # Stage 3: Sum the results
251    {
252        echo "Stage 3: Summing..."
253        local sum=0
254        while read -r num; do
255            ((sum += num))
256        done
257        echo "  Total sum: $sum"
258    } < "$fifo2"
259
260    # Wait for all stages
261    wait
262
263    rm -f "$fifo1" "$fifo2"
264    echo
265}
266
267# --- Demo 6: Monitoring with timeout ---
268demo_timeout() {
269    echo "6. FIFO with Timeout"
270    echo "--------------------"
271
272    local fifo="/tmp/demo_fifo_timeout"
273    mkfifo "$fifo"
274
275    # Slow producer
276    {
277        sleep 2
278        echo "Delayed message"
279    } > "$fifo" &
280    local producer_pid=$!
281
282    echo "Consumer: Waiting for message (3 second timeout)..."
283
284    # Read with timeout using a background process
285    {
286        sleep 3
287        echo "TIMEOUT"
288    } > "$fifo" &
289    local timeout_pid=$!
290
291    # Read first message that arrives
292    IFS= read -r message < "$fifo"
293
294    if [[ "$message" == "TIMEOUT" ]]; then
295        echo "  Result: Timed out!"
296        kill $producer_pid 2>/dev/null || true
297    else
298        echo "  Result: Got message: '$message'"
299        kill $timeout_pid 2>/dev/null || true
300    fi
301
302    wait 2>/dev/null || true
303
304    rm -f "$fifo"
305    echo
306}
307
308# Main execution
309main() {
310    demo_basic_fifo
311    demo_producer_consumer
312    demo_bidirectional
313    demo_load_balancing
314    demo_pipeline
315    demo_timeout
316
317    echo "=== All Demos Complete ==="
318}
319
320main "$@"