If you think about it, computers are very stupid. Even the most powerful CPU can’t do much. However, it can accomplish what it does very quickly and reproducibly. Computers are so fast that they seem to be able to do many things at the same time, and modern computers have multiple CPUs to further enhance their multitasking capabilities. However, we usually don’t write programs or shell scripts to take advantage of this. But, as you will see, there is no reason for this.
Bash support
It is very easy to run multiple processes under Bash. On the one hand, the processes on both sides of the pipeline run together, which is probably the most common way for shell scripts to use multiple programs.In other words, think about what happens if you write ls | more
.
Under the old MSDOS system, the first program will run to completion, and its output will be spooled to a temporary file. Then the second program will run, reading input from the same file. For Linux and most other modern operating systems, these two programs will run with the input of the second program connected to the output of the first program.
This is easy because the program is synchronized on the input and output channels. However, it is equally easy to start multiple programs independently. The key is to use “&” to separate programs or end script lines.
The conversion script is easy, for example:
find /mnt1/usr -name '*.so' >/tmp/libs1 find /mnt2/usr -name '*.so' > /tmp/libs2 # to find /mnt1/usr -name '*.so' >/tmp/libs1 & find /mnt2/usr -name '*.so' > /tmp/libs2 &
In the first case, the search is performed once at a time and only continues after the last search run. In the second case, the two commands are running at the same time, and the script will continue to run even if the two commands are still running.
problem
There is only one problem. Although you can split multiple programs and run them together, it is rare that these programs do not need to be coordinated with each other.
Not that it is useful to run these in parallel, but look at the output of this command:
alw@Enterprise:~$ banner hello & banner goodbye [1] 173 # # ###### # # #### #### #### #### ##### ##### # # ###### # # # # # # # # # # # # # # # # # # # # ###### ##### # # # # # # # # # # # ##### # ##### # # # # # # # # ### # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # ###### ###### ###### #### #### #### #### ##### ##### # ###### [1]+ Done banner hello
Not what you expected. Depending on your system, the first program may (or may not) complete all output at once. Interspersed output is not what you really want.
control
There are other questions. You may want to find out the PID of the new process.you can use it bash job control. However, you really don’t need to go that far.
This jobs
The command will display what you are running in the background of the current shell.If you add -l
Either -p
You can also learn PID.
An easier way to learn the PID of a command is to use $!
Of course, if you run from the shell’s command prompt, it will also tell you the PID of the last command run. E.g:
ls / & echo PID=$! [2] 178 PID=178
Of course, your PID number will almost certainly be different.
and then?
Armed with PID, what can you do with it? You will find two things most useful.First, you can use wait
Know when one (or more) processes are completed.
Another thing you can do is to use kill
Send a signal to the background program. This is beyond the scope of this article, but you can use signals to create complex communication between programs or invoke default behaviors such as termination.
one example
Consider a case where you have a bunch of jpeg
Files and you want to convert them to png
Use of files on the website ImageMagick
. You can try this simple script:
#!/bin/bash for I in *.jpg do convert "$I" "png/$(basename "$I" .jpg).png" done echo Copying files now... ls png
This will get the job done.Probably, there will be some file copy commands on the last line, such as sftp
Follow it, but I used a directory listing just as an example.
Instead, you can initiate all conversions at once, utilize multiple processors, and then wait for them all to complete. If there are no waiting commands, the analog copy will start before the conversion is complete, unless very few conversions are required.
#!/bin/bash for I in *.jpg do convert "$I" "png/$(basename "$I" .jpg).png" & done wait echo Copying files now... ls png
Still a problem
still have a question. The wait command will wait for any child processes active in the shell. This may not be what you want, although in this case, it may be fine. But let’s fix it:
#!/bin/bash PIDs="" for I in *.jpg do convert "$I" "png/$(basename "$I" .jpg).png" & PIDs+="$! " done wait $PIDs echo Copying files... ls png
If you run the timing with a large number of files, you will see a big difference. On my laptop with a few photos, the direct version takes about 40 seconds. The final version only took more than 10 seconds.
wrap up
It’s easy to forget that you can easily do more than one thing at a time. Of course, this also opens up a whole new problem area. If you need to protect your programs from each other, check out our previous post on the key parts.Not everyone thinks bash
It is a great programming language, but its features are surprising. Although it may not be suitable for all tasks, it is very useful for some tasks.