Cet article est purement pratique et est dédié à ma triste histoire.
En préparant
Zero Touch PROD pour RDS (MS SQL), dont toutes nos oreilles bourdonnaient, j'ai fait une présentation (POC - Proof Of Concept) de l'automatisation: un ensemble de scripts PowerShell. Après la présentation, lorsque les applaudissements bruyants et prolongés se sont calmés, se transformant en une ovation incessante, on m'a dit que tout cela était bien, mais seulement pour des raisons idéologiques, nous avons tous des esclaves Jenkins sous Linux!
Est-ce possible? Prendre un tube DBA aussi chaud sous Windows et le mettre dans la chaleur même de PowerShell sous Linux? N'est-ce pas cruel?
J'ai dû plonger dans cette étrange combinaison de technologie. Bien sûr, tous mes 30+ scripts ont cessé de fonctionner. À ma grande surprise, en un jour ouvrable, j'ai réussi à tout réparer. J'écris en pleine poursuite. Alors, quels pièges pouvez-vous rencontrer lors du portage de scripts PowerShell de Windows vers Linux?
sqlcmd vs Invoke-SqlCmd
Permettez-moi de vous rappeler la principale différence entre eux. Le bon vieil utilitaire
sqlcmd fonctionne
également sous Linux, avec des fonctionnalités presque identiques. Pour exécuter la requête, nous passons -Q, le fichier d'entrée comme -i et la sortie -o. Voici juste les noms de fichiers, bien entendu, rendus sensibles à la casse. Si vous utilisez -i, écrivez dans le fichier à la fin:
GO EXIT
S'il n'y a pas de sortie à la fin, alors sqlcmd ira attendre l'entrée, et s'il n'y a pas de
GO avant la
sortie , la dernière commande ne fonctionnera pas. Toutes les sorties, les sélections, les messages, l'impression, etc., parviennent au fichier de sortie.
Invoke-SqlCmd renvoie le résultat sous la forme d'un DataSet, DataTables ou DataRows. Par conséquent, si vous pouvez traiter le résultat d'une simple sélection via
sqlcmd , en
analysant sa sortie, la sortie de quelque chose de compliqué est presque impossible: il y a
Invoke-SqlCmd pour cela. Mais cette équipe a ses propres blagues:
- Si vous lui passez le fichier via -InputFile , alors EXIT n'est pas nécessaire, de plus, il donne une erreur de syntaxe
- -OutputFile non, la commande vous renvoie le résultat sous forme d'objet
- Il existe deux syntaxes pour spécifier un serveur: -ServerInstance -Username -Password -Database et via -ConnectionString . Curieusement, dans le premier cas, vous ne pouvez pas spécifier un port autre que 1433.
- la sortie de texte, de type PRINT, qui est «interceptée» par sqlcmd de manière élémentaire, est un problème pour Invoke-SqlCmd
- Et surtout: cette applet de commande n'est probablement pas dans votre Linux!
Et c'est le principal problème. Ce n'est qu'en mars que cette applet de commande
est devenue disponible pour les plates-formes non Windows , et enfin nous pouvons avancer!
Substitution variable
Sqlcmd a une substitution de variable avec -v, comme ceci:
Dans le script SQL, nous utilisons des substitutions:
set @spid=$(spid) set @age=$(age)
Alors voilà. Dans * nix
, les substitutions de variables ne fonctionnent pas . L'
option -v est ignorée.
Invoke-SqlCmd ignore
-Variables . Bien que le paramètre qui définit les variables elles-mêmes soit ignoré, les substitutions elles-mêmes fonctionnent - vous pouvez utiliser toutes les variables de Shell. Cependant, j'ai été offensé par les variables et j'ai décidé de ne pas en dépendre du tout, et j'ai agi de manière approximative et primitive, car les scripts pour sql sont courts:
Comme vous le comprenez, il s'agit d'un test de la version Unix.
Importer des fichiers
Dans la version Windows, toute opération que j'avais eu était accompagnée d'un audit: nous avons effectué sqlcmd, obtenu une sorte d'abus dans le fichier de sortie, attaché ce fichier à la plaque d'audit. Heureusement, SQL Server fonctionnait sur le même serveur que Jenkins, cela a été fait comme ceci:
CREATE procedure AuditUpload @id int, @filename varchar(256) as set nocount on declare @sql varchar(max) CREATE TABLE
Ainsi, nous avalons l'intégralité du fichier BCP et poussons la table d'audit dans le champ nvarchar (max). Bien sûr, tout ce système s'est effondré, car au lieu de SQL Server, j'ai obtenu RDS, et BULK INSERT ne fonctionne pas sur \\ UNC à cause de la tentative de prendre un verrou exclusif sur un fichier, et avec RDS, cela est généralement voué à l'échec depuis le début. J'ai donc décidé de changer la conception du système, en stockant l'audit ligne par ligne:
CREATE TABLE AuditOut ( ID int NULL, TextLine nvarchar(max) NULL, n int IDENTITY(1,1) PRIMARY KEY )
Et écrivez à ce tableau comme ceci:
function WriteAudit([string]$Filename, [string]$ConnStr, [string]$Tabname, [string]$Jobname) {
Pour sélectionner le contenu, sélectionnez par ID, en choisissant n (identité) dans l'ordre.
Dans le prochain article, je m'attarderai plus en détail sur la façon dont tout cela interagit avec Jenkins.