📜 ⬆️ ⬇️

Using bat files to deploy applications

In the process of work I had to face one task. There is some product that runs under Windows and consists of several components - the kernel, protocol, bridge, and delivery channel. Part of the component is written in Java, part in C ++. Delivery channels can be from one to twenty. Each component uses its own database (MS SQL Server acts as a DBMS). For components written in Java, the database structure is created automatically; for components written in C ++, the structure must be created manually by an SQL script. Each component should work as a service in the system. All this good must be thoroughly tested. For each test it is necessary to recreate the database and system services.

Having done this thing once, I thought, and how could this process be automated as much as possible (actions are not complicated, but routine). The solution should be simple and does not require the installation of any software. Therefore, immediately the choice fell on an ancient, but time-tested script file in the embedded command language - Bat. At the same time, we will check what bat scripts are still capable of.

All of our actions using the script will try to log. To do this, set the name of the log file:
@ set LOGFILE = "log.% DATE% _% TIME: ~ 0.2% -% TIME: ~ 3.2% -% TIME: ~ 6.2% .txt"

We get a file like this on output: log.14.02.2012_10-41-42.txt
However, if you are an amateur working in the morning or late at night, it may turn out like this: log.14.02.2012_ 1-03-28.txt
We are happy to review your suggestions on how to fix this.

UPD. Thanks to everyone, especially DJnK for a more elegant solution:
for / f "tokens = 1-4 delims =:" %% a in ( 'echo% time: ~ 0.8%' ) do set mytime = %% a_ %% b_ %% c

')
We set the choice of the action in the batch file, which will be passed to it as the first parameter
@ rem INSTALL or REMOVE
set ACTION = % 1


Set the string to connect to the database:
@ rem Format: < ComputerName > < InstanceName > or just IP
@ rem If neither the -U parameter nor the -P parameter is specified, the sqlcmd program tries to connect using the Microsoft Windows authentication mode.
@ rem This uses the Windows user account that started the sqlcmd program.
set url_db = "(local)"


Further for each component we set specific parameters. Whether to work with the component, or not (y or n) will be set from the parameters
@ rem Fill in these parameters, y - if we create a global database for the kernel
@ set WorkWhisKernel = % 2
@ set KernelDbName = Kernel
@ set KernelUserName = Kernel
@ set KernelUserPassw = Kernel
@ rem Recovery model for the database. FULL values ​​available | BULK_LOGGED | SIMPLE
@ set KernelRecovery_mode = SIMPLE

@ rem Fill in these parameters, y - if we create a database for the channel
@ set WorkWhisChannel = % 3
@ set ChannelDbName = Channel
@ set ChannelDbCount = 10
@ set ChannelUserName = Channel
@ set ChannelUserPassw = Channel
@ rem Recovery model for the database. FULL values ​​available | BULK_LOGGED | SIMPLE
@ set ChannelRecovery_mode = SIMPLE
@ rem Use the "_" character to separate the database name and its number. For example test_1 or test1
@ set Use_underline = y
@ rem Database Version for Channel
@ set ChannelVersion = mssql.Channel_5.4.3.2

@ rem Fill in these parameters, y - if we create a database for Bridge
@ set WorkWhisBridge = % 4
@ set BridgeDbName = Bridge
@ set BridgeUserName = Bridge
@ set BridgeUserPassw = Bridge
@ rem Recovery model for the database. FULL values ​​available | BULK_LOGGED | SIMPLE
@ set BridgeRecovery_mode = SIMPLE
@ rem Database version for Bridge
@ set BridgeVersion = mssql.Bridge_1.1.3


Further, depending on the type of action with the base (INSTALL or REMOVE), and also on whether you need to work with this component, we will perform certain actions.
For convenience, actions on the database are rendered into separate sql scripts. We will work through the utility sqlcmd. If MSSQL Server is not installed on your machine, then sqlcmd can be downloaded and used as part of the SQL Server Express Utility distribution .

if "% WorkWhisI_k%" == "y" (
if "% ACTION%" == "INSTALL" (
@ rem Create a global database for Kernel and the user and its
sqlcmd -S % url_db % -i Kernel.sql >> % LOGFILE %
)
if "% ACTION%" == "REMOVE" (
@ rem Delete the DB informer_kernel and its user
sqlcmd -S % url_db % -i KernelDel.sql >> % LOGFILE %
)
)


As you can see, everything is very simple. However, there is a small problem, namely how to transfer the names of the database, user, etc. in SQL script called via sqlcmd?
In fact, everything is very simple:
- Create a login for the database
CREATE LOGIN $ ( KernelUserName )
WITH PASSWORD = '$ (KernelUserPassw)' , CHECK_POLICY = OFF;
GO

--We create a database
USE master;
CREATE DATABASE $ ( KernelDbName ) ;
GO

- Set DB recovery mode
ALTER DATABASE $ ( KernelDbName ) SET RECOVERY $ ( KernelRecovery_mode )
GO

--Create a user for the database
USE $ ( KernelDbName ) ;
CREATE USER $ ( KernelUserName ) FOR LOGIN $ ( KernelUserName )
WITH DEFAULT_SCHEMA = dbo;
GO

- assign a role to the user
USE $ ( KernelDbName ) ;
EXEC sp_addrolemember 'db_owner' , '$ (KernelUserName)'
GO


Similar lines will be for the component Bridge. But for the Channel component we will have, say, ten. Therefore, we add a simple loop:
for / L %% i in ( 1 , 1 , % ChannelDbCount % ) do (
if "% Use_underline%" == "y" (
@ set ChannelDbNameCounter = % ChannelDbName % _ %% i
) else (
@ set ChannelDbNameCounter = % ChannelDbName %%% i
)
% ChannelDbNameCounter %
@ rem Create a database cp_service
sqlcmd -S % url_db % -i Channel.sql >> % LOGFILE %
@ rem Create a database structure for cp_service
sqlcmd -S % url_db % -i % ChannelVersion % .sql >> % LOGFILE %
)


Next, we install the services of our components in the system (I will give an example only for the Channel components):
@ rem Number of Channels
SET ChannelDbCount = 10
@ rem Startup Type < boot | system | auto | demand | disabled | error >
SET run_type = demand
@ rem Service dependencies ( separated by / ( forward slash ) )
SET depend = MSSQLSERVER

for / L %% i in ( 1 , 1 , % ChannelDbCount % ) do (
@ rem install the service Channel. To install a component as a service, its internal implementation is used.
ruby Channel %% i.exe --install
@ rem for the service set 3 reboot with an interval of 1 min. if a fatal error has occurred
sc failure Channel %% i reset = 240 actions = restart / 60000 / restart / 60000 / restart / 600000
@ rem startup type of service < boot | system | auto | demand | disabled | error > and dependencies < Dependencies ( separated by / ( forward slash ) ) >
sc config Channel %% i start = % run_type % depend = % depend %
)

We start the installed services:
for / L %% i in ( 1 , 1 , % ChannelDbCount % ) do (
sc start Channel %% i
)


I will not give the code for stopping and deleting services, since he is identical.

Now we will put together everything we wrote about earlier.
Run product deployment script with install.bat yyy parameters

@ rem Run our main script with parameters to create databases
DbManage.bat INSTALL % 1 % 2 % 3

@ rem Install Services
InstallServices.bat

@ rem Run all services
StartServices.bat


Run product uninstall script with install.bat yyy parameters
@ rem Stop services if they are running.
StopServices.bat

@ rem Making a groove so that all services have time to stop
@ rem This method may not work in non-server Windows
timeout / t 10

@ rem Delete old services
RemoveServices.bat

@ rem Run the main script with the parameters for removal
start DbManage.bat REMOVE % 1 % 2 % 3


As a result, we received the implementation of all the desired actions, which are written at the beginning of this opus with a minimal amount of effort, namely, by launching a regular batch file with several parameters.
Implementation of course is not perfect, but performs its functions. The good old "batch file" is still capable of something, although it is time to switch to PoverShell. However, there are some difficulties there, in particular with certificates and signing scripts.

In general, as they say, there is no perfect solution.

Source: https://habr.com/ru/post/138162/


All Articles