Artikel ini murni praktis dan didedikasikan untuk kisah sedih saya.
Mempersiapkan
Zero Touch PROD untuk RDS (MS SQL), tentang mana semua telinga kita berdengung, saya membuat presentasi (POC - Proof Of Concept) otomatisasi: satu set skrip PowerShell. Setelah presentasi, ketika tepuk tangan yang meriah dan berkepanjangan mereda, menjadi tepuk tangan tanpa henti, mereka mengatakan kepada saya bahwa semua ini baik, tetapi hanya untuk alasan ideologis kita semua memiliki budak Jenkins yang berjalan di Linux!
Apakah itu mungkin? Untuk mengambil yang hangat, tabung DBA dari bawah Windows dan memasukkannya ke dalam panas PowerShell di Linux? Bukankah itu kejam?
Saya harus menyelami kombinasi teknologi yang aneh ini. Tentu saja, semua 30+ skrip saya berhenti berfungsi. Yang mengejutkan saya, dalam satu hari kerja saya berhasil memperbaiki semuanya. Saya menulis dalam pengejaran. Jadi, jebakan apa yang bisa Anda temui saat porting skrip PowerShell dari Windows ke Linux?
sqlcmd vs Invoke-SqlCmd
Biarkan saya mengingatkan Anda tentang perbedaan utama di antara mereka. Utilitas
sqlcmd tua yang baik
juga bekerja di Linux, dengan fungsi yang hampir sama. Untuk mengeksekusi query, kita mengirimkan -Q, file input sebagai -i, dan output -o. Ini hanya nama file, tentu saja, dibuat case-sensitive. Jika Anda menggunakan -i, tulis di file di akhir:
GO EXIT
Jika tidak ada EXIT di akhir, maka sqlcmd akan menunggu input, dan jika tidak ada
GO sebelum
EXIT , perintah terakhir tidak akan berfungsi. Semua output, pilih, pesan, cetak, dll., Sampai ke file output.
Invoke-SqlCmd mengembalikan hasilnya sebagai DataSet, DataTables atau DataRows. Oleh karena itu, jika Anda dapat memproses hasil pemilihan sederhana melalui
sqlcmd ,
mem -
parsing outputnya, maka mengeluarkan sesuatu yang rumit hampir tidak mungkin: ada
Invoke-SqlCmd untuk ini. Tetapi tim ini memiliki lelucon sendiri:
- Jika Anda meneruskan file ke sana melalui -InputFile , maka EXIT tidak diperlukan, apalagi, itu memberikan kesalahan sintaksis
- -OutputFile tidak, perintah mengembalikan Anda hasilnya sebagai objek
- Ada dua sintaks untuk menentukan server: -ServerInstance -Username -Password -Database dan melalui -ConnectionString . Anehnya, dalam kasus pertama, Anda tidak dapat menentukan port selain 1433.
- output teks, dari tipe PRINT, yang "ditangkap" oleh sqlcmd dengan cara dasar, merupakan masalah untuk Invoke-SqlCmd
- Dan yang terpenting: cmdlet ini kemungkinan besar tidak ada di Linux Anda!
Dan ini adalah masalah utama. Hanya pada bulan Maret cmdlet ini
tersedia untuk platform non-windows , dan akhirnya kita dapat bergerak maju!
Substitusi variabel
Sqlcmd memiliki substitusi variabel dengan -v, seperti:
Dalam skrip SQL, kami menggunakan substitusi:
set @spid=$(spid) set @age=$(age)
Jadi disini. Di * nix
, substitusi variabel tidak berfungsi .
Opsi -v diabaikan.
Invoke-SqlCmd mengabaikan
-Variabel . Meskipun parameter yang mengatur variabel itu sendiri diabaikan, pergantian itu berfungsi - Anda bisa menggunakan variabel apa pun dari Shell. Namun, saya tersinggung oleh variabel dan memutuskan untuk tidak bergantung pada mereka sama sekali, dan saya bertindak kasar dan primitif, karena skrip untuk sql pendek:
Ini, seperti yang Anda pahami, adalah ujian dari versi Unix.
Unggah file
Dalam versi Windows, setiap operasi yang saya lakukan disertai dengan audit: mereka melakukan sqlcmd, mendapat semacam penyalahgunaan dalam file output, melampirkan file ini ke plat audit. Untungnya, SQL server bekerja pada server yang sama dengan Jenkins, itu dilakukan seperti ini:
CREATE procedure AuditUpload @id int, @filename varchar(256) as set nocount on declare @sql varchar(max) CREATE TABLE
Dengan demikian, kami menelan seluruh file BCP, dan mendorong tabel audit di bidang nvarchar (maks). Tentu saja, seluruh sistem ini hancur, karena alih-alih SQL server yang saya dapatkan RDS, dan BULK INSERT tidak bekerja di \\ UNC karena upaya untuk mengambil kunci eksklusif ke file, dan dengan RDS ini pada awalnya hancur. Jadi saya memutuskan untuk mengubah desain sistem, menyimpan garis audit demi baris:
CREATE TABLE AuditOut ( ID int NULL, TextLine nvarchar(max) NULL, n int IDENTITY(1,1) PRIMARY KEY )
Dan tulis ke tabel ini seperti ini:
function WriteAudit([string]$Filename, [string]$ConnStr, [string]$Tabname, [string]$Jobname) {
Untuk memilih konten, pilih berdasarkan ID, pilih n (identitas) secara berurutan.
Pada artikel selanjutnya saya akan membahas lebih detail tentang bagaimana semua ini berinteraksi dengan Jenkins.