Sign up ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It's 100% free, no registration required.

I have the following test script.

#!/bin/bash

function foo {
  printf "Test line break: $1\nafter line break\n\n"
}

for VARIABLE in {1..30}
do
  foo $VARIABLE &
done
wait

Now I executed the script several times, and some times the output looks like that:

Test line break: 15
Test line break: 14
after line break: 14
after line break: 15


Test line break: 16
after line break: 16

instead of the expected:

Test line break: 15
after line break: 15

Test line break: 14
after line break: 14

Test line break: 16
after line break: 16

how can I prevent that printf "interrupts" another printf, but still running it in the background?

For me it seems, that the problem is the "\n" inside printf.

share|improve this question
    
If you're going to use printf remember that its first string is actually a format string and so understands % as a format character. You would be better with printf "%s" ""Test line break: $1\nafter line break\n\n" or even printf "Test line break: %s\nafter line break\n\n" "$1" –  roaima Sep 7 at 19:19

1 Answer 1

up vote 5 down vote accepted

In fact you need a mutex :

Each sub-shell will access concurrently to the same /dev/stdout of the parent shell, so you can not ensure the order even inside the same function. To ensure it you need a lock which enforce the mutual exclusion i.e. : all other processes won't start to write in /dev/stdout until the lock is released.

#!/bin/bash

function foo {
lockdir=/tmp/myscript.lock
 mkdir "$lockdir" 2>/dev/null
while [ $? -ne 0 ]; do mkdir "$lockdir" 2>/dev/null; done
printf "Test line break: $1\nafter line break: $1\n\n"
rm -rf $lockdir
}

for VARIABLE in {1..30}
do
  foo $VARIABLE &
done
wait

This will give this as a result :

$ bash plop1 2>/dev/null
Test line break: 5
after line break: 5

Test line break: 3
after line break: 3

Test line break: 11
after line break: 11

Test line break: 23
after line break: 23

Test line break: 14
after line break: 14

Test line break: 17
after line break: 17

Test line break: 24
after line break: 24

Test line break: 21
after line break: 21

Test line break: 27
after line break: 27

Test line break: 6
after line break: 6

Test line break: 2
after line break: 2

Test line break: 9
after line break: 9

Test line break: 26
after line break: 26

Test line break: 29
after line break: 29

Test line break: 20
after line break: 20

Test line break: 1
after line break: 1

Test line break: 12
after line break: 12

Test line break: 4
after line break: 4

Test line break: 13
after line break: 13

Test line break: 10
after line break: 10

Test line break: 15
after line break: 15

Test line break: 28
after line break: 28

Test line break: 25
after line break: 25

Test line break: 19
after line break: 19

Test line break: 18
after line break: 18

Test line break: 8
after line break: 8

Test line break: 7
after line break: 7

Test line break: 16
after line break: 16

Test line break: 22
after line break: 22

Test line break: 30
after line break: 30
share|improve this answer
2  
you can also have a look at this excellent wiki : wiki.bash-hackers.org/howto/mutex –  netmonk Sep 7 at 13:03
    
thank you! But is it possible without having to type 2>/dev/null? –  sam Sep 7 at 13:24
    
yes, you just have to add it inside the function ! i just edited the script –  netmonk Sep 7 at 13:25
    
very cool, thanks –  sam Sep 7 at 13:28

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.