Выбрать главу

make with no options then makes sure that aliases.db and access.db are up-to-date. Since there is no command as part of all, no file called all will be created. Thus, make always thinks that all is out-of-date ("Doesn't exist" equals "Is out of date"). You'll soon see why that is important.

Remember that make is lazy. If access.db is out-of-date but the other file isn't, it just runs the commands to bring access.db up-to-date. In fact, if bringing access.db up-to-date required something else, and that required something else, and so on, make would very intelligently do just the minimum work required.

In addition to all, I usually include a couple of other useful commands: reload: postfix reload stop: postfix stop start: postfix start

Think about what that means. If I run make reload, make is going to notice that there is no file called reload, so it will run postfix reload thinking that the command will create a file called reload. Ah ha! I fooled them, didn't I? The command I listed tells postfix to reload its configuration. That command doesn't create a file called reload at all! Therefore, the next time I run make reload, make will run the command again. In other words, if you want something to always happen, make sure the recipe simply doesn't create the file that make is expecting to create.

With the above code in my Makefile, I can reload, stop, and start postfix by typing make reload, make stop, or make start, respectively. If there are other things that should be stopped (for example, an IMAP server, web-based email client, and so on), I can include commands to do those things in the recipes. I don't have to remember all the commands.

This is a good time for me to point out a little lie that I told earlier. I said that each recipe begins with the file that is going to be created, followed by a colon, and then it lists the files that make up the main file. make doesn't know whether those files really make up the file to be created. There's no way it could tell. Those items listed after the colon are really just dependencies that must be up-to-date.

Here's a simple Makefile from a system that runs Postfix and includes recipes for rebuilding the index for aliases and access. You'll notice that at the top are some constants (NEWALISES, PDIR, and so on) that are used throughout the file. Also, a backward slash (\) at the end of the line is used to continue long lines: NEWALISES=/usr/sbin/newaliases PDIR=/etc/postfix POSTMAP=/usr/local/postfix/sbin/postmap # The "commands" alclass="underline" $(PDIR)/aliases.pag $(PDIR)/aliases.dir \ $(PDIR)/access.dir $(PDIR)/access.pag reload reload: postfix reload stop: postfix stop start: postfix start # # When aliases changes, generate the .pag and .dir files # $(PDIR)/aliases.pag $(PDIR)/aliases.dir: $(PDIR)/aliases $(NEWALIASES) # # When access changes, generate the .pag and .dir files # $(PDIR)/access.dir $(PDIR)/access.pag: $(PDIR)/access $(POSTMAP) $(PDIR)/access

Now I can edit either aliases or access and type make. I don't have to remember that the commands to update the indexes are extremely different. And I don't have to remember to tell postfix to reload its configuration each time because the all recipe includes that. The reload at the end of all will trigger that recipe every time.

make can also be useful for keeping files on various servers up-to-date. For example, let's suppose the aliases file in our example needs to be the same on both of our email servers. We decide that we'll update the file on this server, and push it to server2. That recipe might look like this: push.aliases.done: $(PDIR)/aliases scp $(PDIR)/aliases server2:$(PDIR)/aliases touch $@

We push the file to server2 using scp, then touch a file called push.aliases.done. Since this file is created after the successful copy of the file, we can build recipes so that the push is only done if it's absolutely needed. We can also force the file to be recopied by simply deleting the push.aliases.done file and typing make. Traditionally, there is a recipe called clean that deletes all the *.done files and other machine-generated files.

There is nothing special about files that end with .done. It is simply customary to name-flag or timestamp files with .done at the end.

Here's a complete example. There are two files that need indexing if they change: aliases and access. If either of them has been reindexed, postfix is told to reload. They also are both pushed to server2 if they change. Finally, the command cd /etc && make is sent to server2 if and only if one or more of the files has been pushed to it.

By carefully constructing the recipes with proper dependencies, and touching *.done files where required, make will do the absolute minimal amount of work to bring the system up-to-date: # # Makefile for server1 # NEWALISES=/usr/sbin/newaliases PDIR=/etc/postfix POSTMAP=/usr/local/postfix/sbin/postmap # # High-level "commands" # alclass="underline" aliases.done access.done reload_if_needed.done push push: push.done reload: postfix reload stop: postfix stop start: postfix start reload_if_needed.done: aliases.done access.done postfix reload touch reload_if_needed.done clean: rm -f \ $(PDIR)/aliases.pag $(PDIR)/aliases.dir \ $(PDIR)/access.dir $(PDIR)/access.pag \ push.aliases.done push.access.done reload_if_needed.done # # Recipes for particular files that need indexing/regeneration # # When aliases changes, generate the .pag and .dir files aliases.done: $(PDIR)/aliases.pag $(PDIR)/aliases.dir $(PDIR)/aliases.pag $(PDIR)/aliases.dir: $(PDIR)/aliases $(NEWALIASES) # When access changes, generate the .pag and .dir files access.done: $(PDIR)/access.dir $(PDIR)/access.pag $(PDIR)/access.dir $(PDIR)/access.pag: $(PDIR)/access $(POSTMAP) $(PDIR)/access # # pushes # push.done: push.aliases.done push.access.done ssh server2 "cd /etc && make" touch $@ push.aliases.done: aliases.done scp $(PDIR)/aliases server2:$(PDIR)/aliases touch $@ push.access.done: access.done scp $(PDIR)/access server2:$(PDIR)/access touch $@

This Makefile is a good starting point for you to use on your systems. It is rather sophisticated because we do things to make sure Postfix isn't reloaded unless absolutely necessary.