The tasks you are describing can be solved in multiple ways. No one way is "best" as each has its own pros and cons.
The industry as a whole has been evolving from scripts, to configuration management to immutable systems.
As an example, to manage the web.config of an IIS web server, you issue appcmd.exe commands. We use Chef and the IIS cookbook to abstract the appcmd.exe command idempotent resources.
iis_config "session sql_provider" do cfg_cmd "Foobar/# -section:system.web/sessionState /+\"providers.[name='#',connectionString='#',type='#']\"" action :set notifies :restart, 'iis_site[mysite]' end
Here everything inside '#{}' is a chef variable. If the resource runs, it triggers a restart of the IIS service.
The advantage of not using appcmd.exe directly, but abstracting it away to a resource, is that a resource can easily take variables as parameters. This way you can write your code once, but use it in multiple datacenters and environments. The end goal is to be able to write a policy for every type of server, and let the configuration management put the server in alignment with the policy.
Another example of managing a logging config file inside chef.
template "#/log4net.config.xml" do source 'wwwroot/log4net.config.erb' variables( :log_level => node['web']['log4net']['log_level'] ) action :create end
The xml file is then "templateized" as an erb template. Everything inbetween <%= -%> is a variable
<?xml version="1.0" encoding="utf-8" ?> <configuration> <log4net> <root> <level value="<%= @log_level -%>"/>
You can then run chef on a schedule, so that if the variable ever changes. The config management puts the file into the desired state.
Ansible,Chef,Puppet and Salt all operate on very similar principles.