diff --git a/CNAME b/CNAME new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ + diff --git a/ads.txt b/ads.txt new file mode 100644 index 000000000..ff26bce2c --- /dev/null +++ b/ads.txt @@ -0,0 +1 @@ +google.com, pub-3097623931513783, DIRECT, f08c47fec0942fa0 \ No newline at end of file diff --git a/apache-nifi-json-to-sql-replacing-underscore.html b/apache-nifi-json-to-sql-replacing-underscore.html new file mode 100644 index 000000000..890a24615 --- /dev/null +++ b/apache-nifi-json-to-sql-replacing-underscore.html @@ -0,0 +1,411 @@ + + + + + + + + Apache Nifi JSON to SQL Replacing underscore - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Apache Nifi JSON to SQL Replacing underscore

+
+ +
+
+ +
+

Recently I was doing some ETL with Apache NiFi. But after a few minutes of drawing my flow, I saw that the component ConvertJSONToSQL was replacing the underscore ('_') from the field name in the where condition (I was preparing an Update SQL). That was weird because, at the set statement, the field name was kept intact. After some research, I found that the property (see bellow) Translate Field Names was responsible for that weird replacement.

+

Apache NiFi JSONToSQL config

+

Before setting it to FALSE, be aware that the properties on your JSON data must match exactly the name of your fields.

+
+ + +
+
+

Translations:

+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/apache-nifi-json-to-sql-replacing-underscore.html.gz b/apache-nifi-json-to-sql-replacing-underscore.html.gz new file mode 100644 index 000000000..b11afd9a2 Binary files /dev/null and b/apache-nifi-json-to-sql-replacing-underscore.html.gz differ diff --git a/archives.html b/archives.html new file mode 100644 index 000000000..e0b560d79 --- /dev/null +++ b/archives.html @@ -0,0 +1,358 @@ + + + + + + + + Sipmann - Archives + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+

Archives for Sipmann

+ +
+
Mon 21 December 2020
+
Monitoring MySQL restarts with PowerShell
+
Wed 09 December 2020
+
Changing a MySQL user password across multiple application instances without downtime
+
Wed 02 December 2020
+
Apache Nifi JSON to SQL Replacing underscore
+
Sat 14 November 2020
+
Blocking a user on SQL Server based on a schedule
+
Wed 28 October 2020
+
How to set columns on select using Entity Framework
+
Tue 20 October 2020
+
Zabbix Running on Low Memory Mode
+
Wed 14 October 2020
+
Monitoring MySQL Replication Status with PowerShell
+
Sat 03 October 2020
+
Microsoft Against Covid
+
Mon 21 September 2020
+
The power of PowerShell
+
Wed 29 July 2020
+
Top Level Statement in C# 9
+
Thu 02 July 2020
+
Zabbix poller processes more than 75%
+
Mon 22 June 2020
+
Monitoring a Website heath with Azure Functions
+
Tue 09 June 2020
+
Azure Data Fundamentals certification with 80% discount
+
Mon 25 May 2020
+
Zabbix ICMP pinger processes more than 75%
+
Thu 27 February 2020
+
Zabbix Server Out of Memory
+
Thu 03 October 2019
+
Flutter + firebase auth crashing
+
Fri 06 September 2019
+
Removing a user from SQL Server database who owns a schema
+
Mon 12 August 2019
+
Limiting Connection Resources on SQL Server
+
Tue 30 July 2019
+
Using git hooks to easy your life
+
Fri 13 April 2018
+
Microservices with NodeJS, Express.js and RabbitMQ Part 2
+
Wed 04 April 2018
+
Microservices with NodeJS, Express.js and RabbitMQ Part 1
+
Thu 29 March 2018
+
Connecting to a database through SSH
+
Sat 24 March 2018
+
Now posting on Grepora
+
Sat 17 March 2018
+
Scaffolding a React app with Parcel and Yeoman
+
Fri 09 March 2018
+
Could not open connection with MySQL and Hibernate
+
Sun 04 March 2018
+
Solving java.net.SocketException: Protocol family unavailable on a Java + Docker + WildFly
+
Tue 27 February 2018
+
Change display settings on linux with Disper
+
Sat 17 February 2018
+
Java - Files.readAllBytes throws OutOfMemory
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/archives.html.gz b/archives.html.gz new file mode 100644 index 000000000..3b9f29dfb Binary files /dev/null and b/archives.html.gz differ diff --git a/author/mauricio-camargo-sipmann.html b/author/mauricio-camargo-sipmann.html new file mode 100644 index 000000000..a85109067 --- /dev/null +++ b/author/mauricio-camargo-sipmann.html @@ -0,0 +1,603 @@ + + + + + + + + Sipmann - Articles by Maurício Camargo Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+ +
+
+
+

Apache Nifi JSON to SQL Replacing underscore

+
+ +
+
+ +
+

Recently I was doing some ETL with Apache NiFi. But after a few minutes of drawing my flow, I saw that the component ConvertJSONToSQL was replacing the underscore ('_') from the field name in the where condition (I was preparing an Update SQL). That was weird because, at the set …

+
+ + + +
+
+
+
+ +
+
+ + + + + + + +
+

So, you use Entity Framework Core, and you usually code your selects like the following, maybe you are getting too much data.

+
var products = Products
+    .Where(p => p.UnitsInStock > 0)
+    .OrderBy(p => p.ProductName)
+    .ToList()
+
+ +

Running the query above, on my table, you'll get the following output, take a look …

+
+ + + +
+
+
+
+
+ + + + + +
+

Zabbix Running on Low Memory Mode

+
+ +
+
+ +
+

Hey folks, another Zabbix post today. This one it's about increasing the Zabbix Server Cache. It's pretty common (if you have the default settings only) get a warning about your Zabbix value cache running on low memory mode at your dashboard or logs.

+

Zabbix Dashboard warning about the memory problem +Zabbix Dashboard cache graph 70% used

+

To solve, go back to your Zabbix …

+
+ + + +
+
+
+
+
+ + + + + + + +
+

I've been migration some bash scripts that I have to PowerShell, and it's time to migrate a script that monitors the replication of a MySQL database. The credit for the original script goes to Paweł. It's a simple script where I seek a few tags/fields that we get from …

+
+ + + +
+
+
+
+
+
+

Microsoft Against Covid

+
+ +
+
+ +
+

Has your job been affected by covid? Well, last week I've posted on Grepora about a Free Certification Voucher that Microsoft was giving away at the Microsoft Ignite event. After that, I found that they were also giving a huge discount to people who have had their job affected by …

+
+ + + +
+
+
+
+
+ + + + + +
+

The power of PowerShell

+
+ +
+
+ +
+

As a long time Linux user, I've automated a few things with bash scripts and stayed away from PowerShell... I've moved to a Windows environment a few years ago and still, haven gave a shot to PS. But why not? I've made a few scripts to automate some tasks at …

+
+ + + +
+
+
+
+
+ + + + + +
+

Top Level Statement in C# 9

+
+ +
+
+ +
+

Hey folks, I'm coming along to tell you a few things about the new feature of C# 9. Every time you want to start a new project, you always have the same Main File, with the same structure. At the next version of C# (version 9), we'll have a new …

+
+ + + +
+
+
+
+
+ + 1 + 2 + 3 + » + +
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/author/mauricio-camargo-sipmann.html.gz b/author/mauricio-camargo-sipmann.html.gz new file mode 100644 index 000000000..ac5140e54 Binary files /dev/null and b/author/mauricio-camargo-sipmann.html.gz differ diff --git a/author/mauricio-camargo-sipmann2.html b/author/mauricio-camargo-sipmann2.html new file mode 100644 index 000000000..1c75f73de --- /dev/null +++ b/author/mauricio-camargo-sipmann2.html @@ -0,0 +1,582 @@ + + + + + + + + Sipmann - Articles by Maurício Camargo Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Zabbix poller processes more than 75%

+
+ +
+
+ +
+

Hey folks, this is the third post about tweaking the Zabbix configurations. All changes that I've suggested here were based on a Zabbix Server with 50+ hosts. Another thing that can happen to your server, it's the poller get overwhelmed by the amount of servers that need to be polled …

+
+ + + +
+
+
+
+
+ + + + + + + +
+

Sometimes you get your self in need to monitor a website's health or it's content for changes. Of course, there's plenty of options out there, but for the sake of curiosity, let's code our own to see what we can do. First things first. Everything you'll see here, you can …

+
+ + + +
+
+
+
+
+ + + + + + + +
+

Hey folks, if you want to achieve some certification this year, keep an eye open for vouchers. A few months ago, Oracle released a set of free courses with certifications. Now it's Microsoft time. Microsoft is updating they're certifications and we have a voucher of 80% discount using the coupon …

+
+ + + +
+
+
+
+
+
+

Zabbix ICMP pinger processes more than 75%

+
+ +
+
+ +
+

So your monitoring sytems have grown and your zabbix started loggin "Zabbix icmp pinger processes more than 75% busy" at the dashboard.

+

Dashboard do zabbix avisando sobre o erro

+

All you have to do is open your config file (/etc/zabbix/zabbix_server.conf) and find the a tag named StartPingers. It'll be commented by default. Uncomment it …

+
+ + + +
+
+
+
+
+
+

Zabbix Server Out of Memory

+
+ +
+
+ +
+

Do you have a crashing Zabbix Server and looking through the log /var/log/zabbix/zabbix_server.log you see the following out of memory message?

+
__mem_malloc: skipped 0 asked 24 skip_min 18446744073709551615 skip_max 0
+[file:dbconfig.c,line:94] __zbx_mem_realloc(): out of memory (requested 16 bytes)
+[file:dbconfig.c,line …

+
+ + + +
+
+
+
+
+
+

Flutter + firebase auth crashing

+
+ +
+
+ +
+

Hey Folks, recently I've started learning Flutter and right after a TODO List, I tried a Firebase integration. But as soon as I started setting the dependencies, my app stopped opening... just a crash. After a few logs digging, I've found the following log.

+
AndroidRuntime: FATAL EXCEPTION: main
+AndroidRuntime: Process …

+
+ + + +
+
+
+
+
+ + +
+

Your customer urge you to drop a user from the MsSQL Server database, but you stuck with the following related error:

+
Error: 15138 The database principal owns a schema in the database, and cannot be dropped.
+
+ +

That means that the user owns one or more shcemas of your database. If …

+
+ + + +
+
+
+
+
+ + + + + +
+

Limiting Connection Resources on SQL Server

+
+ +
+
+ +
+

Have you ever suffered from a slow SQLServer database? Someone love to run that heavy query in the database? Resource Governor to the rescue. You can set a few rules on how users (connections actually) will use the server/database resources based on a few things.

+

First things first, if …

+
+ + + +
+
+
+
+
+
+

Using git hooks to easy your life

+
+ +
+
+ +
+

Hey folks, it's been a time since my last post. In the meantime, I moved to another state, changed job, and started learning new kinds of stuff. Today I would like to share one thing that I usually do with my small git projects. Git has many cool features, git …

+
+ + + +
+
+
+
+ +
+
+ « + + 1 + 2 + 3 + » + +
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/author/mauricio-camargo-sipmann2.html.gz b/author/mauricio-camargo-sipmann2.html.gz new file mode 100644 index 000000000..9117e33ec Binary files /dev/null and b/author/mauricio-camargo-sipmann2.html.gz differ diff --git a/author/mauricio-camargo-sipmann3.html b/author/mauricio-camargo-sipmann3.html new file mode 100644 index 000000000..1ac098ebe --- /dev/null +++ b/author/mauricio-camargo-sipmann3.html @@ -0,0 +1,526 @@ + + + + + + + + Sipmann - Articles by Maurício Camargo Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+ + + + + + + +
+

This is the first part of a microservices development series. The service will consist of the bellow architecture, where we will expose an image optimizer service that will forward the request to a RabbitMQ queue and answer with the bytecode of the optimized image. It shouldn't be a long series …

+
+ + + +
+
+
+
+
+
+

Connecting to a database through SSH

+
+ +
+
+ +
+

If someday, for some reason, you need to establish a connection with a database which is behind a firewall and you only have SSH access on that server (and you don't want to use a CLI) you can do an SSH tunnel. It's pretty simple, bellow has a sample of …

+
+ + + +
+
+
+
+
+
+

Now posting on Grepora

+
+ +
+
+ +
+

A few weeks ago I started posting at Grepora blog. If you like or are looking for some Oracle related stuff, Grepora it's a good place to go and spend a time reading :). From time to time I'll be posting there, it doesn't mean that this blog will be closed …

+
+ + + +
+
+
+
+
+ + + + + + + +
+

Since Parcel JS arrived, I've been using it a lot as an awesome alternative for WebPack. Webpack isn't bad but IMO it's too complex for the job and parcel do the same (at least the basic) with almost zero configuration. But if you need to create many apps (like a …

+
+ + + +
+
+
+
+
+ + + + + + + +
+

Last day I decided to deploy a MySQL Docker image to work with my Java application. I've been using PostgreSQL instead and have no problems at all, but after I moved to MySQL, the app didn't connect anymore with the database and throw some "Could not open connection" at my …

+
+ + + +
+
+
+
+ +
+
+ + + + + +
+

Change display settings on linux with Disper

+
+ +
+
+ +
+

From time to time, I change the Linux distro on my laptop or just do a fresh install on it. And once in a while, have random problems with external displays. It can be something really "simple" like don't detecting the external monitor or something crazy like the image below …

+
+ + + +
+
+
+
+
+
+

Java - Files.readAllBytes throws OutOfMemory

+
+ +
+
+ +
+

When you need to interact with files, there's the possibility to read all bytes from the file with Files.readAllBytes. But be aware of the kinds of files your application will deal with because the Java API files have a limit for the buffer that is defined as Integer.MAX_VALUE …

+
+ + + +
+
+
+
+
+ « + + 1 + 2 + 3 + +
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/author/mauricio-camargo-sipmann3.html.gz b/author/mauricio-camargo-sipmann3.html.gz new file mode 100644 index 000000000..e43dd9024 Binary files /dev/null and b/author/mauricio-camargo-sipmann3.html.gz differ diff --git a/authors.html b/authors.html new file mode 100644 index 000000000..a8950bff5 --- /dev/null +++ b/authors.html @@ -0,0 +1,302 @@ + + + + + + + + Sipmann - Authors + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+

Authors on Sipmann

+ +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/authors.html.gz b/authors.html.gz new file mode 100644 index 000000000..6ace4f846 Binary files /dev/null and b/authors.html.gz differ diff --git a/azure-data-fundamentals-certification-80-discount.html b/azure-data-fundamentals-certification-80-discount.html new file mode 100644 index 000000000..84ae29e20 --- /dev/null +++ b/azure-data-fundamentals-certification-80-discount.html @@ -0,0 +1,511 @@ + + + + + + + + Azure Data Fundamentals certification with 80% discount - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+ + +
+

Hey folks, if you want to achieve some certification this year, keep an eye open for vouchers. A few months ago, Oracle released a set of free courses with certifications. Now it's Microsoft time. Microsoft is updating they're certifications and we have a voucher of 80% discount using the coupon DP900Norfolk at the checkout of the beta certification DP-900.

+

Be aware that this certification is in beta and the result won't be instantly available as the regular ones. Access the following link and schedule your exam. https://docs.microsoft.com/pt-br/learn/certifications/exams/dp-900.

+

Update: There is a 80% voucher also for https://docs.microsoft.com/en-us/learn/certifications/azure-ai-fundamentals. Voucher: AI900Saratoga

+
+ + +
+
+

Translations:

+
    +
+
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/azure-data-fundamentals-certification-80-discount.html.gz b/azure-data-fundamentals-certification-80-discount.html.gz new file mode 100644 index 000000000..e21348ea9 Binary files /dev/null and b/azure-data-fundamentals-certification-80-discount.html.gz differ diff --git a/blocking-user-on-sql-server-based-on-schedule.html b/blocking-user-on-sql-server-based-on-schedule.html new file mode 100644 index 000000000..d9634d139 --- /dev/null +++ b/blocking-user-on-sql-server-based-on-schedule.html @@ -0,0 +1,566 @@ + + + + + + + + Blocking a user on SQL Server based on a schedule - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Blocking a user on SQL Server based on a schedule

+
+ +
+
+ +
+

Ok, some time ago, I've posted about how you can set limits to connections on SQL Server using the Resource Governor. But what if you can't use it? You always can block logins using a login trigger, but I don't like the idea of having selects running on every login. So I came across with a solution using a stored procedure, a table and the Agent.

+

The main idea is, store the time that a user must be blocked and using the Agent, disable or enable the user. Bellow you can see the table (the table is in Portuguese, but I have a few comment blocks to help you).

+
CREATE TABLE dbo.HorariosBloqueio (
+    Id INT NOT NULL,
+    LoginName NVARCHAR(100) NOT NULL,
+    HrInicio TIME NOT NULL, /* Startint block time */
+    HrTermino TIME NOT NULL, /* Ending block time */
+    Bloqueado INT DEFAULT 0, /* 0 = unblocked, 1 = blocked */
+    PRIMARY KEY (Id)
+);
+GO
+
+/* Don't block the SA user, precautions, you know */
+ALTER TABLE dbo.HorariosBloqueio
+    ADD CONSTRAINT chk_users CHECK (LoginName not in ('sa'));
+
+ALTER TABLE dbo.HorariosBloqueio
+    ADD CONSTRAINT chk_hora_final_maior CHECK (HrTermino > HrInicio);
+
+ALTER TABLE dbo.HorariosBloqueio
+    ADD CONSTRAINT chk_status_bloqueio CHECK (Bloqueado in (0, 1));
+
+CREATE SEQUENCE dbo.seq_HorariosBloqueio START WITH 1 INCREMENT BY 1;
+GO
+
+ +

After creating the table, let's check the procedure that will handle the enabling/disabling the users. Be aware that on the procedure, I've set the database name where the table was stored, you can change it replacing the DBATOOLS text to the database name where you created the table.

+
IF OBJECT_ID('dbo.sp_ValidarLogin') IS NULL
+  EXEC ('CREATE PROCEDURE dbo.sp_ValidarLogin AS RETURN 0;');
+GO
+
+CREATE OR ALTER PROC dbo.sp_ValidarLogin
+AS BEGIN
+    DECLARE @LoginName AS NVARCHAR(100);
+    DECLARE @Momento AS TIME;
+    SET @Momento = CAST(GETDATE() AS TIME);
+
+    /* Block the ones that aren't blocked already and maches the time */
+    DECLARE block_cursor CURSOR
+        FOR SELECT LoginName FROM [DBATOOLS].[dbo].[HorariosBloqueio] WHERE Bloqueado = 0 AND HrInicio <= @Momento AND HrTermino >= @Momento
+    OPEN block_cursor;
+
+    FETCH NEXT FROM block_cursor INTO @LoginName
+
+    WHILE @@FETCH_STATUS = 0
+    BEGIN
+        exec ('ALTER LOGIN ' + @LoginName + ' DISABLE;');
+
+        print 'Bloqued usuario ' + @LoginName;
+
+        FETCH NEXT FROM block_cursor INTO @LoginName
+    END;
+
+    CLOSE block_cursor;
+    DEALLOCATE block_cursor;
+
+    UPDATE [DBATOOLS].[dbo].[HorariosBloqueio] SET Bloqueado = 1 WHERE HrInicio <= @Momento AND HrTermino >= @Momento
+
+
+    /* Enable up who was blocked */
+    DECLARE unblock_cursor CURSOR
+        FOR SELECT LoginName FROM [DBATOOLS].[dbo].[HorariosBloqueio] WHERE Bloqueado = 1 AND (HrInicio > @Momento OR HrTermino < @Momento)
+    OPEN unblock_cursor ;
+
+    FETCH NEXT FROM unblock_cursor  INTO @LoginName
+
+    WHILE @@FETCH_STATUS = 0
+    BEGIN
+        exec ('ALTER LOGIN ' + @LoginName +' ENABLE;');
+
+        print 'Unbloqued usuario ' + @LoginName;
+
+        FETCH NEXT FROM unblock_cursor  INTO @LoginName
+    END;
+
+    CLOSE unblock_cursor;
+    DEALLOCATE unblock_cursor;
+
+    UPDATE [DBATOOLS].[dbo].[HorariosBloqueio] SET Bloqueado = 0 WHERE Bloqueado = 1 AND (HrInicio > @Momento OR HrTermino < @Momento)
+END;
+
+ +

Ok, so now all you have to do, is schedule a job to run that stored procedure from minute to minute. Again, the main idea is tell the procedure when a user must be blocked and when it'll be unblocked.

+
    -- Will block the user protheus from 10 AM till 15 PM
+    INSERT INTO dbo.HorariosBloqueio (Id, LoginName, HrInicio, HrTermino) VALUES (NEXT VALUE FOR seq_HorariosBloqueio, 'protheus', '10:00:00', '15:00:00');
+

+
+ + +
+
+

Translations:

+ +
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blocking-user-on-sql-server-based-on-schedule.html.gz b/blocking-user-on-sql-server-based-on-schedule.html.gz new file mode 100644 index 000000000..2feded0af Binary files /dev/null and b/blocking-user-on-sql-server-based-on-schedule.html.gz differ diff --git a/categories.html b/categories.html new file mode 100644 index 000000000..36ecb0b4c --- /dev/null +++ b/categories.html @@ -0,0 +1,312 @@ + + + + + + + + Sipmann - Categories + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+

Categories on Sipmann

+ +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/categories.html.gz b/categories.html.gz new file mode 100644 index 000000000..d4bf6bb2b Binary files /dev/null and b/categories.html.gz differ diff --git a/category/azure.html b/category/azure.html new file mode 100644 index 000000000..6f4fe1cd7 --- /dev/null +++ b/category/azure.html @@ -0,0 +1,370 @@ + + + + + + + + Sipmann - Azure category + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Microsoft Against Covid

+
+ +
+
+ +
+

Has your job been affected by covid? Well, last week I've posted on Grepora about a Free Certification Voucher that Microsoft was giving away at the Microsoft Ignite event. After that, I found that they were also giving a huge discount to people who have had their job affected by …

+
+ + + +
+
+
+
+
+ + + + + + + +
+

Sometimes you get your self in need to monitor a website's health or it's content for changes. Of course, there's plenty of options out there, but for the sake of curiosity, let's code our own to see what we can do. First things first. Everything you'll see here, you can …

+
+ + + +
+
+
+
+
+ + + + + + + +
+

Hey folks, if you want to achieve some certification this year, keep an eye open for vouchers. A few months ago, Oracle released a set of free courses with certifications. Now it's Microsoft time. Microsoft is updating they're certifications and we have a voucher of 80% discount using the coupon …

+
+ + + +
+
+
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/category/azure.html.gz b/category/azure.html.gz new file mode 100644 index 000000000..b43528b19 Binary files /dev/null and b/category/azure.html.gz differ diff --git a/category/flutter.html b/category/flutter.html new file mode 100644 index 000000000..6ae2b125d --- /dev/null +++ b/category/flutter.html @@ -0,0 +1,304 @@ + + + + + + + + Sipmann - Flutter category + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Flutter + firebase auth crashing

+
+ +
+
+ +
+

Hey Folks, recently I've started learning Flutter and right after a TODO List, I tried a Firebase integration. But as soon as I started setting the dependencies, my app stopped opening... just a crash. After a few logs digging, I've found the following log.

+
AndroidRuntime: FATAL EXCEPTION: main
+AndroidRuntime: Process …

+
+ + + +
+
+
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/category/flutter.html.gz b/category/flutter.html.gz new file mode 100644 index 000000000..b68127e1b Binary files /dev/null and b/category/flutter.html.gz differ diff --git a/category/front-end.html b/category/front-end.html new file mode 100644 index 000000000..8949bcfd1 --- /dev/null +++ b/category/front-end.html @@ -0,0 +1,375 @@ + + + + + + + + Sipmann - Front-end category + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+ + + + + + + +
+

This is the first part of a microservices development series. The service will consist of the bellow architecture, where we will expose an image optimizer service that will forward the request to a RabbitMQ queue and answer with the bytecode of the optimized image. It shouldn't be a long series …

+
+ + + +
+
+
+
+
+ + + + + + + +
+

Since Parcel JS arrived, I've been using it a lot as an awesome alternative for WebPack. Webpack isn't bad but IMO it's too complex for the job and parcel do the same (at least the basic) with almost zero configuration. But if you need to create many apps (like a …

+
+ + + +
+
+
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/category/front-end.html.gz b/category/front-end.html.gz new file mode 100644 index 000000000..16c100acd Binary files /dev/null and b/category/front-end.html.gz differ diff --git a/category/java.html b/category/java.html new file mode 100644 index 000000000..12cb89a65 --- /dev/null +++ b/category/java.html @@ -0,0 +1,370 @@ + + + + + + + + Sipmann - Java category + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+ + + + + + + +
+

Last day I decided to deploy a MySQL Docker image to work with my Java application. I've been using PostgreSQL instead and have no problems at all, but after I moved to MySQL, the app didn't connect anymore with the database and throw some "Could not open connection" at my …

+
+ + + +
+
+
+
+ +
+
+
+

Java - Files.readAllBytes throws OutOfMemory

+
+ +
+
+ +
+

When you need to interact with files, there's the possibility to read all bytes from the file with Files.readAllBytes. But be aware of the kinds of files your application will deal with because the Java API files have a limit for the buffer that is defined as Integer.MAX_VALUE …

+
+ + + +
+
+
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/category/java.html.gz b/category/java.html.gz new file mode 100644 index 000000000..206c02a7a Binary files /dev/null and b/category/java.html.gz differ diff --git a/category/linux.html b/category/linux.html new file mode 100644 index 000000000..1feae1512 --- /dev/null +++ b/category/linux.html @@ -0,0 +1,460 @@ + + + + + + + + Sipmann - Linux category + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+ + + + + +
+

Zabbix Running on Low Memory Mode

+
+ +
+
+ +
+

Hey folks, another Zabbix post today. This one it's about increasing the Zabbix Server Cache. It's pretty common (if you have the default settings only) get a warning about your Zabbix value cache running on low memory mode at your dashboard or logs.

+

Zabbix Dashboard warning about the memory problem +Zabbix Dashboard cache graph 70% used

+

To solve, go back to your Zabbix …

+
+ + + +
+
+
+
+
+
+

Zabbix poller processes more than 75%

+
+ +
+
+ +
+

Hey folks, this is the third post about tweaking the Zabbix configurations. All changes that I've suggested here were based on a Zabbix Server with 50+ hosts. Another thing that can happen to your server, it's the poller get overwhelmed by the amount of servers that need to be polled …

+
+ + + +
+
+
+
+
+
+

Zabbix ICMP pinger processes more than 75%

+
+ +
+
+ +
+

So your monitoring sytems have grown and your zabbix started loggin "Zabbix icmp pinger processes more than 75% busy" at the dashboard.

+

Dashboard do zabbix avisando sobre o erro

+

All you have to do is open your config file (/etc/zabbix/zabbix_server.conf) and find the a tag named StartPingers. It'll be commented by default. Uncomment it …

+
+ + + +
+
+
+
+
+
+

Zabbix Server Out of Memory

+
+ +
+
+ +
+

Do you have a crashing Zabbix Server and looking through the log /var/log/zabbix/zabbix_server.log you see the following out of memory message?

+
__mem_malloc: skipped 0 asked 24 skip_min 18446744073709551615 skip_max 0
+[file:dbconfig.c,line:94] __zbx_mem_realloc(): out of memory (requested 16 bytes)
+[file:dbconfig.c,line …

+
+ + + +
+
+
+
+
+
+

Connecting to a database through SSH

+
+ +
+
+ +
+

If someday, for some reason, you need to establish a connection with a database which is behind a firewall and you only have SSH access on that server (and you don't want to use a CLI) you can do an SSH tunnel. It's pretty simple, bellow has a sample of …

+
+ + + +
+
+
+
+
+ + + + + +
+

Change display settings on linux with Disper

+
+ +
+
+ +
+

From time to time, I change the Linux distro on my laptop or just do a fresh install on it. And once in a while, have random problems with external displays. It can be something really "simple" like don't detecting the external monitor or something crazy like the image below …

+
+ + + +
+
+
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/category/linux.html.gz b/category/linux.html.gz new file mode 100644 index 000000000..916b4e9c2 Binary files /dev/null and b/category/linux.html.gz differ diff --git a/category/mysql.html b/category/mysql.html new file mode 100644 index 000000000..1e0de87fd --- /dev/null +++ b/category/mysql.html @@ -0,0 +1,307 @@ + + + + + + + + Sipmann - MySQL category + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/category/mysql.html.gz b/category/mysql.html.gz new file mode 100644 index 000000000..cfca5f836 Binary files /dev/null and b/category/mysql.html.gz differ diff --git a/category/net.html b/category/net.html new file mode 100644 index 000000000..9b1fd7350 --- /dev/null +++ b/category/net.html @@ -0,0 +1,348 @@ + + + + + + + + Sipmann - .NET category + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+ + + + + + + +
+

So, you use Entity Framework Core, and you usually code your selects like the following, maybe you are getting too much data.

+
var products = Products
+    .Where(p => p.UnitsInStock > 0)
+    .OrderBy(p => p.ProductName)
+    .ToList()
+
+ +

Running the query above, on my table, you'll get the following output, take a look …

+
+ + + +
+
+
+
+
+ + + + + +
+

Top Level Statement in C# 9

+
+ +
+
+ +
+

Hey folks, I'm coming along to tell you a few things about the new feature of C# 9. Every time you want to start a new project, you always have the same Main File, with the same structure. At the next version of C# (version 9), we'll have a new …

+
+ + + +
+
+
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/category/net.html.gz b/category/net.html.gz new file mode 100644 index 000000000..c5251e200 Binary files /dev/null and b/category/net.html.gz differ diff --git a/category/powershell.html b/category/powershell.html new file mode 100644 index 000000000..1a8236810 --- /dev/null +++ b/category/powershell.html @@ -0,0 +1,379 @@ + + + + + + + + Sipmann - PowerShell category + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+ + + + + + + +
+

I've been migration some bash scripts that I have to PowerShell, and it's time to migrate a script that monitors the replication of a MySQL database. The credit for the original script goes to Paweł. It's a simple script where I seek a few tags/fields that we get from …

+
+ + + +
+
+
+
+
+ + + + + +
+

The power of PowerShell

+
+ +
+
+ +
+

As a long time Linux user, I've automated a few things with bash scripts and stayed away from PowerShell... I've moved to a Windows environment a few years ago and still, haven gave a shot to PS. But why not? I've made a few scripts to automate some tasks at …

+
+ + + +
+
+
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/category/powershell.html.gz b/category/powershell.html.gz new file mode 100644 index 000000000..fb724849b Binary files /dev/null and b/category/powershell.html.gz differ diff --git a/category/random.html b/category/random.html new file mode 100644 index 000000000..b51fb2ffd --- /dev/null +++ b/category/random.html @@ -0,0 +1,302 @@ + + + + + + + + Sipmann - Random category + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Now posting on Grepora

+
+ +
+
+ +
+

A few weeks ago I started posting at Grepora blog. If you like or are looking for some Oracle related stuff, Grepora it's a good place to go and spend a time reading :). From time to time I'll be posting there, it doesn't mean that this blog will be closed …

+
+ + + +
+
+
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/category/random.html.gz b/category/random.html.gz new file mode 100644 index 000000000..15134310d Binary files /dev/null and b/category/random.html.gz differ diff --git a/category/sql-server.html b/category/sql-server.html new file mode 100644 index 000000000..359194eb1 --- /dev/null +++ b/category/sql-server.html @@ -0,0 +1,375 @@ + + + + + + + + Sipmann - SQL Server category + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+ + +
+

Your customer urge you to drop a user from the MsSQL Server database, but you stuck with the following related error:

+
Error: 15138 The database principal owns a schema in the database, and cannot be dropped.
+
+ +

That means that the user owns one or more shcemas of your database. If …

+
+ + + +
+
+
+
+
+ + + + + +
+

Limiting Connection Resources on SQL Server

+
+ +
+
+ +
+

Have you ever suffered from a slow SQLServer database? Someone love to run that heavy query in the database? Resource Governor to the rescue. You can set a few rules on how users (connections actually) will use the server/database resources based on a few things.

+

First things first, if …

+
+ + + +
+
+
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/category/sql-server.html.gz b/category/sql-server.html.gz new file mode 100644 index 000000000..ee681a4d8 Binary files /dev/null and b/category/sql-server.html.gz differ diff --git a/category/tools.html b/category/tools.html new file mode 100644 index 000000000..cc6f7935c --- /dev/null +++ b/category/tools.html @@ -0,0 +1,331 @@ + + + + + + + + Sipmann - Tools category + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Apache Nifi JSON to SQL Replacing underscore

+
+ +
+
+ +
+

Recently I was doing some ETL with Apache NiFi. But after a few minutes of drawing my flow, I saw that the component ConvertJSONToSQL was replacing the underscore ('_') from the field name in the where condition (I was preparing an Update SQL). That was weird because, at the set …

+
+ + + +
+
+
+
+
+
+

Using git hooks to easy your life

+
+ +
+
+ +
+

Hey folks, it's been a time since my last post. In the meantime, I moved to another state, changed job, and started learning new kinds of stuff. Today I would like to share one thing that I usually do with my small git projects. Git has many cool features, git …

+
+ + + +
+
+
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/category/tools.html.gz b/category/tools.html.gz new file mode 100644 index 000000000..daa90a7a9 Binary files /dev/null and b/category/tools.html.gz differ diff --git a/cloud-not-open-connection-java-mysql-hibernate.html b/cloud-not-open-connection-java-mysql-hibernate.html new file mode 100644 index 000000000..c0c139e64 --- /dev/null +++ b/cloud-not-open-connection-java-mysql-hibernate.html @@ -0,0 +1,474 @@ + + + + + + + + Could not open connection with MySQL and Hibernate - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+ + +
+

Last day I decided to deploy a MySQL Docker image to work with my Java application. I've been using PostgreSQL instead and have no problems at all, but after I moved to MySQL, the app didn't connect anymore with the database and throw some "Could not open connection" at my face, but why? I've tried to connect to it manually and got the same problem.

+

After some research, I found that the true error should be java.sql.SQLException: null, message from server: "Host '172.17.0.4' is not allowed to connect to this MySQL server" but it wasn't showing to me...

+

After all, be aware that with the docker image MySQL:5.7.21 (latest version right now) the root user isn't allowed to remote connect to the database (it's alright, security reasons) and if you still want to do remote connections to it with root there are a few things you can do.

+
    +
  1. Create a user or allow root to access from other IPs.
  2. +
+
#No access to user root on any other IP
+SELECT User, Host FROM mysql.user;
++---------------+-----------+
+| User          | Host      |
++---------------+-----------+
+| healthchecker | localhost |
+| root          | localhost |
++---------------+-----------+
+2 rows in set (0.01 sec)
+
+CREATE USER 'newuser'@'%' IDENTIFIED BY 'password'; #% mean any IP
+GRANT ALL PRIVILEGES ON *.* TO 'newuser'@'%';   #*.* mean database.table ;)
+
+
    +
  1. Use MariaDB instead, witch come (at least on the version 10.2.13) with root allowed to do remote connections and will work like MySQL :)
  2. +
+

I changed to MariaDB as it work without creating user or any changes on the Java code or the docker run command.

+

+
+ + +
+
+

Translations:

+
    +
+
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/cloud-not-open-connection-java-mysql-hibernate.html.gz b/cloud-not-open-connection-java-mysql-hibernate.html.gz new file mode 100644 index 000000000..01a8c7b6b Binary files /dev/null and b/cloud-not-open-connection-java-mysql-hibernate.html.gz differ diff --git a/connecting_to_database_through_ssh.html b/connecting_to_database_through_ssh.html new file mode 100644 index 000000000..18f6fa64b --- /dev/null +++ b/connecting_to_database_through_ssh.html @@ -0,0 +1,463 @@ + + + + + + + + Connecting to a database through SSH - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Connecting to a database through SSH

+
+ +
+
+ +
+

If someday, for some reason, you need to establish a connection with a database which is behind a firewall and you only have SSH access on that server (and you don't want to use a CLI) you can do an SSH tunnel. It's pretty simple, bellow has a sample of how to allow connections to a remote Firebird database.

+
ssh -L 3051:192.168.1.9:3050 username@192.168.1.9
+
+

The -L parameter tells to SSH do a local port forwarding on local port 3051 to remote port 3050. You can use it to a connection with many services, not just databases.

+

You can do the reverse kind of tunnel, forward connections from the host to your local machine, you just have to change the parameter form "-L" to "-R" and the port order is inverted, first come the port where the server will listen and after your localhost port. This remote port forwarding must be enabled on the server. Look for GatewayPorts at the ssh config file.

+
ssh -R 3050:localhost:3050 username@192.168.1.9
+
+

Why whould you need something like that?? Let's say you want to share a localhost site/database with a friend, but your internet connection don't allow you to expose any port but you have access to a remote server witch can do that. Problem solved ;).

+

+
+ + +
+
+

Translations:

+
    +
+
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/connecting_to_database_through_ssh.html.gz b/connecting_to_database_through_ssh.html.gz new file mode 100644 index 000000000..2e242d2b6 Binary files /dev/null and b/connecting_to_database_through_ssh.html.gz differ diff --git a/drafts/cloud-not-open-connection-java-mysql-hibernate-pt.html b/drafts/cloud-not-open-connection-java-mysql-hibernate-pt.html new file mode 100644 index 000000000..0e6cf9218 --- /dev/null +++ b/drafts/cloud-not-open-connection-java-mysql-hibernate-pt.html @@ -0,0 +1,474 @@ + + + + + + + + Could not open connection com MySQL e Hibernate - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+ + +
+

Last day I decided to deploy a MySQL Docker image to work with my Java application. I've been using PostgreSQL instead and have no problems at all, but after I moved to MySQL, the app didn't connect anymore with the database and throw some "Could not open connection" at my face, but why? I've tried to connect to it manually and got the same problem.

+

After some research, I found that the true error should be java.sql.SQLException: null, message from server: "Host '172.17.0.4' is not allowed to connect to this MySQL server" but it wasn't showing to me...

+

After all, be aware that with the docker image MySQL:5.7.21 (latest version right now) the root user isn't allowed to remote connect to the database (it's alright, security reasons) and if you still want to do remote connections to it with root there are a few things you can do.

+
    +
  1. Create a user or allow root to access from other IPs.
  2. +
+
#No access to user root on any other IP
+SELECT User, Host FROM mysql.user;
++---------------+-----------+
+| User          | Host      |
++---------------+-----------+
+| healthchecker | localhost |
+| root          | localhost |
++---------------+-----------+
+2 rows in set (0.01 sec)
+
+CREATE USER 'newuser'@'%' IDENTIFIED BY 'password'; #% mean any IP
+GRANT ALL PRIVILEGES ON *.* TO 'newuser'@'%';   #*.* mean database.table ;)
+
+
    +
  1. Use MariaDB instead, witch come (at least on the version 10.2.13) with root allowed to do remote connections and will work like MySQL :)
  2. +
+

I changed to MariaDB as it work without creating user or any changes on the Java code or the docker run command.

+

+
+ + +
+
+

Translations:

+
    +
+
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/drafts/cloud-not-open-connection-java-mysql-hibernate-pt.html.gz b/drafts/cloud-not-open-connection-java-mysql-hibernate-pt.html.gz new file mode 100644 index 000000000..991b6b0f5 Binary files /dev/null and b/drafts/cloud-not-open-connection-java-mysql-hibernate-pt.html.gz differ diff --git a/drafts/cool-tools-pt.html b/drafts/cool-tools-pt.html new file mode 100644 index 000000000..fc144c64b --- /dev/null +++ b/drafts/cool-tools-pt.html @@ -0,0 +1,456 @@ + + + + + + + + Cool Tools - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Cool Tools

+
+ +
+
+ +
+

Com o passar do tempo você vai "encontrando" - e às vezes até mesmo desenvolvendo - algumas ferramentas que tornam o seu dia a dia como desenvolvedor mais fácil. Abaixo seguem algumas das minhas ferramentas que costumo usar. Ressalto que essa lista será (provavelmente) atualizada com o passar do tempo.

+
+

https://www.gitkraken.com

+

Eu gosto muito de usar git, mas às vezes fico cansado de ter que usar só linha de comando, e achei no GitKreaken uma interface muito legal de se usar.

+
+
+

http://paletton.com

+

Toda vez que você vai fazer um novo sistema/site, ou até mesmo trocar o layout de algum já existente, você acaba tendo que montar uma paleta de cores para se utilizar em todo o template.

+
+
+

https://icomoon.io/app/#/select

+

Querendo usar ícones como fontes? Vá aí e gere apenas os arquivos que você vai realmente utilizar e economize alguns kbs.

+
+
+

https://syncthing.net/

+

Se você procura algum meio de sincronizar seus arquivos entre vários pcs e por algum motivo não quer usar um Google Drive ou DropBox, fica aqui a indicação deste cara.

+
+
+

http://sqitch.org/

+

Gerenciamento de versões de um banco de dados pode ser bem complicado e trabalhoso... Manter diversos ambientes (desenvolvimento, homologação, produção) vai dar um trabalho se não utilizar alguma ferramenta. Porque não usar o melhor de gerenciamento de versão (git) e uma ferramenta que se adequa ao que você precisa? sqitch é o cara nessas horas.

+
+
+

http://www.setupmyproject.com/

+

Preparação de projetos java, com frameworks, bibliotecas, nomenclatura, etc... Rende uma economia de tempo grandiosa e já vem tudo pronto :).

+
+
+

https://www.pexels.com/

+

Bom site para imagens free stock. Excelente local para conseguir imagens de alta qualidade.

+
+
+

https://heml.io/

+

"HEML is an open source markup language for building responsive email." Melhor descrição impossível.

+
+
+

https://www.mockapi.io/

+

Desenvolva mocks para testar seu front-end. Eles geram inclusive uma carga de dados para ser utilizado nos seus testes.

+
+
+

https://undraw.co

+

Needing some cool and free ilustrations? Take a look at it.

+
+
+

https://www.audiotool.com/app/

+

Ferramenta para criar sons, musicas e afins

+
+
+

https://app.cloudskew.com/

+

Desenhar projetos de cloud e afins

+
+
+

https://lottiefiles.com/

+

Veja por si mesmo

+
+

+
+ + +
+
+

Translations:

+
    +
+
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/drafts/cool-tools-pt.html.gz b/drafts/cool-tools-pt.html.gz new file mode 100644 index 000000000..f623a0e21 Binary files /dev/null and b/drafts/cool-tools-pt.html.gz differ diff --git a/drafts/desenvolvendo-app-firefoxos-pt.html b/drafts/desenvolvendo-app-firefoxos-pt.html new file mode 100644 index 000000000..16099d5fc --- /dev/null +++ b/drafts/desenvolvendo-app-firefoxos-pt.html @@ -0,0 +1,489 @@ + + + + + + + + Desenvolvendo apps para o FirefoxOS (Parte 1) - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Desenvolvendo apps para o FirefoxOS (Parte 1)

+
+ +
+
+ +
+

Requisitos mínimos?

+

Para seguir este tutorial você precisará do Nodejs. Utilizaremos ele para automatizar algumas tarefas, como a criação do nosso projeto e até mesmo o empacotamento da app. Estas automatizações se darão pela utilização de algumas aplicações como o Yeoman e o Grunt .

+

Também será necessário o emulador do FirefoxOS, ele roda através do seu navegador Firefox. Para instalá-lo basta ir no menu Ferramentas > Desenvolvedor web > App Manager, nesta tela basta tentar iniciar o emulador, se não possuir um já instalado, você será solicitado a fazê-lo. Neste tutorial irei utilizar a versão 1.4.

+

Preparando o ambiente

+

Tendo o Node instalado, vamos instalar o yeoman e o gerador de app para Firefox OS. Atenção para o parâmetro '-g' no processo de instalação, com ele os seus pacotes serão instalados globalmente, e não só para a pasta em que esta o prompt.

+
npm install -g yo
+npm install -g generator-firefoxos-app
+
+ +

Com ambos os pacotes acima instalados, vamos dar início a criação da app. No seu diretório de projetos ou onde desejar criar a app chama o generator instalado.

+
yo firefoxos-app
+
+ +

Uma vez chamado esse generator, o mesmo irá fazer alguns questionamentos, o primeiro é claro será o nome da sua aplicação, seguido da descrição e o nome do desenvolvedor.

+

Após a execução do generator, você já terá uma estrutura para desenvolvimento pronta, inclusive com um html inicial, com todas as dependências já instaladas. Vale ressaltar agora algumas tarefas disponíveis no Gruntfile.

+
    +
  • Default: Irá gerar o pacote de distribuição
  • +
  • Test: Até a presente versão do generator (0.1.3) este processo irá simplesmente rodar o validador jsHint
  • +
  • Server: Irá disponibilizar na porta 9001 um simples servidor para testar a sua app
  • +
+

Vamos testar a nossa app. Para tal, rode o comando grunt server e acesse no seu navegador localhost:9001 e devemos ver a seguinte app. Caso nenhuma página seja exibida, revise os passos ateriores e verifique se nenhum erro ocorreu.

+

App inicial

+

Vale ressaltar que a sua app toda estará dentro de uma pasta também chamada app. Nela você encontrará os seus arquivos .html, .js, .css e demais. Antes de começarmos a codificar a nossa app, vamos ver como se instala a mesma.

+

Instalando a app

+

Para fins de teste, não é necessário rodar o comando grunt, sendo que ele irá testar o JS e compactar tudo em um arquivo .zip, basta apontar a instalação para a pasta app dentro do seu projeto. "Mas como eu faço isto?".

+

Indo novamente na App Manager, clicando na lateral esquerda, onde indica "Aplicativos", teremos então disponível no inferior da tela duas opções, vamos nos ater a utilizar a primeira (Adicionar aplicativo hospedado).

+

Clicando nesta opção vamos navegar até a pasta da app e clicar selecionada. Pronto.

+

Simples de se instalar, não acha? O Resultado final deve ser semelhante ao abaixo.

+

App inicial

+

Acessando uma API

+

Quando vamos programar algo mais complexo, geralmente vamos utilizar algo como, câmera, rede, lista de contatos, armazenamento e outras possibilidades. Para utilizarmos essas APIs, precisamos - assim como no desenvolvimento para android - especificar para o usuário no momento de instalação. Estes dados de acesso ficam no arquivo manifes.webapp, se você ainda não deu uma olhada neste arquivo, é nele que fica armazenado dados da app, como nome, descrição, versão, localização de ícones e é claro as permissões que a mesma requer.

+

As permissões ficam na propriedade permissions, na forma de "chave" : True. Algumas das apis são:

+
    +
  • câmera
  • +
  • contacts
  • +
  • desktop-notification
  • +
  • storage
  • +
+

Cada permissão vai mudar o tipo de app que você esta desenvolvendo, mas aí eu sugiro ler mais na MDN aqui. Esse é o básico para iniciar no desenvolvimento de app para FirefoxOS. Na parte dois, vou começar a passar um pouco de código.

+
+ + +
+
+

Translations:

+
    +
+
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/drafts/desenvolvendo-app-firefoxos-pt.html.gz b/drafts/desenvolvendo-app-firefoxos-pt.html.gz new file mode 100644 index 000000000..d719890da Binary files /dev/null and b/drafts/desenvolvendo-app-firefoxos-pt.html.gz differ diff --git a/drafts/editando-o-admin-do-django-pt.html b/drafts/editando-o-admin-do-django-pt.html new file mode 100644 index 000000000..ddc1acd55 --- /dev/null +++ b/drafts/editando-o-admin-do-django-pt.html @@ -0,0 +1,530 @@ + + + + + + + + Editando o Admin do Django - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Editando o Admin do Django

+
+ +
+
+ +
+

Este artigo foi re-postado no grupo PythonClub. Vamos falar um pouco sobre como customizar o admin do Django. Primeiramente porque? A resposta é bem simples, quero mostrar algo para o usuário sem que ele precise entrar nas apps e fazer alguma consulta para então tomar alguma ação. Alguns exêmplos para isto seriam:

+
+
    +
  • Exibir as vendas do mês em forma de gráfico por região do país
  • +
  • Exibir os últimos comentários adicionados
  • +
  • Exibir log dos ultimos usuários cadastrados
  • +
+
+

O que faremos aqui será exibir os últimos comentários ainda não liberados de um sistema de blog. Vale lembrar que aqui não discutiremos sobre os primeiros passos da aplicação. Para seguirmos adiante, vamos assumir que já temos um projeto básico com uma estrutura simples, abaixo a estrutura inicial do nosso projeto.

+
../blog/
+├── core
+│   ├── __init__.py
+│   ├── admin.py
+│   ├── models.py
+│   ├── tests.py
+│   └── views.py
+├── blog
+│   ├── __init__.py
+│   ├── settings.py
+│   ├── urls.py
+│   └── wsgi.py
+└── manage.py
+
+

Para iniciarmos, precisamos da nossa tabela de comentários, vamos usar a mais simples e básica o possível.

+ ++++ + + + + + + + + + + + + + + + + + + + +
CampoTipo
nomeVarchar(30)
textoText
liberadoBoolean
dataDate
+

Vamos seguir adiante e alterar a página inicial do admin para listar os últimos comentários de um simples sistema de blog. Para comerçar a editar o admin, precisamos inicialmente copiar o template que desejamos para a pasta uma pasta admin dentro ta pasta de templates do nosso projeto. Isto porque o Admin, não passa de uma app como outra qualquer, portanto o sistema de herança vai funcionar aqui, carregamento prioritariamente o seu template. Você pode conseguir o template que desejar (no nosso caso o index.html) dentro do projeto do Django mesmo, no meu caso "C:\Django-1.6.3\django\contrib\admin\templates\admin".

+
../blog/
+├── templates
+│   ├── admin
+│   │   └── index.html
+├── core
+
+

Tire um tempo e brinque um pouco com este template e veja o que acontece se você alterar algumas coisa. Para adicionarmos a nossa listagem, vamos adicionar um painel lateral, para tal vamos adicionar o código abaixo antes do fechamento da ultima tag div. Nele podemos ver uma chamada para uma template_tag, portanto precisamos carrega-la no topo do template.

+
{% load comentarios_tag %}
+...
+...
+...
+<div class="module" id="ultimos-comentarios">
+    <h2>Ultimos Comentários</h2>
+    <h3>Liberar</h3>
+            {% comentarios_n_liberados %}
+</div>
+
+

Esta template trata-se da responsável por fazer a consulta na base de dados e renderizar a nossa lista, portanto ela é uma 'inclusion tag'. Se você não esta familiarizado com 'template tags', talvez queira dar uma olhada na documentação do django.

+

Vamos então criar nossa template tag 'comentarios_n_liberados'. Primeiro devemos criar uma pasta chamada templatetags, dentro da nossa app core. Dentro ta pasta vamos inicializar um pacote python e criar o arquivo comentarios_tag.py. Nele precisamos declarar nosso metodo que deve se chamar 'comentarios_n_liberados' e nele fazer uma simples consulta ao banco buscando os comentários não liberados e por fim registrar a tag apontando para o template que será renderizado. Abaixo o código mais explicado.

+
+
Recomendações
+ Livro Pense em Python na Amazon + Livro Curso Intensivo de Python na Amazon +
from django import template
+from core import models
+
+#Carrega o registro de template tags
+register = template.Library()
+
+#Registra o metodo a seguir como uma inclusion_tag indicando o template a ser renderizad
+@register.inclusion_tag('comentarios_n_liberados.html')
+def comentarios_n_liberados():
+    comentarios = models.comentario.objects.filter(liberado=False).order_by('data')[0:5]
+    return { 'comentarios' : comentarios }
+
+

Abaixo o html do nosso template a ser renderizado, este deve estar dentro da pasta templates da nossa app core.

+
{% if not comentarios %}
+    <p>Nenhum comentário novo</p>
+{% else %}
+    <ul>
+            {% for c in comentarios %}
+            <li class="addlink">
+                    <a href="{{ c.id }}">{{ c.texto|truncatechars:30 }}</a>
+            </li>
+            {% endfor %}
+    </ul>
+{% endif %}
+
+

Com tudo isto feito, basta subir o seu servidor e ver o resultado final, que pode ser visto na imagem abaixo.

+Resultado final +

Lembrando que aqui apenas mostrei como modificar o index do admin, para apenas listar dados do banco, mas você pode ir muito mais além. Abaixo fica a estrutura de diretórios final e um link para download do projeto funcionando.

+
../blog/
+├── core
+│   ├── templates
+│   │   └── comentarios_n_liberados.html
+│   ├── templatetag
+│   │   └── comentarios_tag.py
+│   ├── __init__.py
+│   ├── admin.py
+│   ├── models.py
+│   ├── tests.py
+│   └── views.py
+├── blog
+│   ├── __init__.py
+│   ├── settings.py
+│   ├── urls.py
+│   └── wsgi.py
+├── templates
+│   ├── admin
+│   │   └── index.html
+└── manage.py
+
+

Espero que tenham gostado, criticas/sugestões são bem-vindas. Fontes do Projeto

+

+
+ + +
+
+

Translations:

+
    +
+
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/drafts/editando-o-admin-do-django-pt.html.gz b/drafts/editando-o-admin-do-django-pt.html.gz new file mode 100644 index 000000000..44fe1e03e Binary files /dev/null and b/drafts/editando-o-admin-do-django-pt.html.gz differ diff --git a/drafts/menu-dinamico-com-apps-do-django-pt.html b/drafts/menu-dinamico-com-apps-do-django-pt.html new file mode 100644 index 000000000..a68d34bb7 --- /dev/null +++ b/drafts/menu-dinamico-com-apps-do-django-pt.html @@ -0,0 +1,518 @@ + + + + + + + + Menu dinâmico com as apps do django - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Menu dinâmico com as apps do django

+
+ +
+
+ +
+

Digamos que sua empresa trabalha com Django desenvolvendo aplicações cujas apps são plugaveis e reutilizáveis. Por que não se aproveitar de um certo padrão de desenvolvimento para desenvolver menus que se modificam de acordo com as apps que estão no projeto? Como o objetivo aqui não é desenvolver uma app em si, vamos utilizar um projeto com algumas de modelo. Se desejar estudar mais sobre desenvolvimento Django, a documentação é muito boa, mas também temos blogs e sites excelentes sobre o assunto.

+

Para conseguirmos atingir esse objetivo, vamos utilizar a api Django.apps que está disponível a partir da versão 1.7. +Com esta api, vamos percorrer as apps e se possível, criar um link para uma URL base de cada uma delas. Para começo, baixe os fontes do projeto aqui, rode o pip install do projeto e no fim, sua estrutura de pastas deve ficar como abaixo.

+
../menusapp/
+├── comentarios
+│   ├── templates
+│   │   └── comentarios
+│   │      └── listagem.html
+│   ├── __init__.py
+│   ├── admin.py
+│   ├── apps.py
+│   ├── models.py
+│   ├── tests.py
+│   ├── urls.py
+│   └── views.py
+├── core
+│   ├── templates
+│   │   └── core
+│   │       └── base.html
+│   │       └── listagem.html
+│   ├── __init__.py
+│   ├── admin.py
+│   ├── apps.py
+│   ├── models.py
+│   ├── tests.py
+│   ├── urls.py
+│   └── views.py
+├── menusapp
+│   ├── __init__.py
+│   ├── settings.py
+│   ├── urls.py
+│   └── wsgi.py
+└── manage.py
+
+

Rode o projeto e veja como é o seu funcionamento. É na app core que temos a base do nosso HTML, então será nele que iremos trabalhar. Quando se trata de algo que será renderizado no template base, eu gosto muito de utilizar 'template tags' para facilitar. +Neste link tem mais um exemplo de utilização de 'template tag' caso esteja interessado.

+

Vamos então criar uma pasta chamada template_tag e dentro dela a nossa tag. Vamos chamá-la de menus_tag.py. Abaixo vamos ver um pouco da nossa tag. +O código é bem simples e auto explicativo, importamos as bibliotecas necessárias e realizamos o @register da tag com o nome do template que será renderizado. +E por ultimo, retornamos uma tupla de dados para o template.

+
+
Recomendações
+ + +
from django import template
+from django.apps import apps
+
+#Carrega o registro de template tags
+register = template.Library()
+
+#Registra o metodo a seguir como uma inclusion_tag indicando o template a ser renderizado
+@register.inclusion_tag('menus_por_app.html')
+def menus_por_app():
+    lst = apps.get_app_configs()
+    return { 'lst_apps' : lst }
+
+

O template está abaixo e é simplesmente um for percorrendo as apps e gerando uma lista com os seus menus. As outras propriedades você pode ver direto na documentação. +Algumas ressalvas para o que foi feito por questões de praticidade para uso posterior, utilizei um with para concatenar e gerar a url e criei um apelido para a url para validar a existência da mesma. Fora isto, nada de novo.

+
{% if not lst_apps %}
+                    <p>Nenhuma app</p>
+            {% else %}
+                    <ul>
+                            {% for app in lst_apps %}
+                                    {% with app.name|add:":listagem" as link %}
+                                            {% url link as the_url %}
+                                                    {% if the_url %}
+                                                    <li>
+                                                            <a href="{% url link %}">{{ app.verbose_name|truncatechars:30 }}</a>
+                                                    </li>
+                                                    {% endif %}
+                                    {% endwith %}
+                            {% endfor %}
+                    </ul>
+            {% endif %}
+
+Resultado final +

No final, o resultado obtido deve ser semelhante ao acima. Repare que está listando as duas aplicações. E acima de tudo, repare que só serão exibidos os links cuja app tenha um namespace de mesmo nome e uma url de nome listagem. +A estrutura final pode ser vista abaixo. Atente-se aos nomes tanto das pastas quanto dos arquivos, pois qualquer diferença pode causar o não funcionamento.

+
../menusapp/
+├── comentarios
+│   ├── templates
+│   │   └── comentarios
+│   │      └── listagem.html
+│   ├── __init__.py
+│   ├── admin.py
+│   ├── apps.py
+│   ├── models.py
+│   ├── tests.py
+│   ├── urls.py
+│   └── views.py
+├── core
+│   ├── templates
+│   │   └── core
+│   │   │   └── base.html
+│   │   │   └── listagem.html
+│   │   └── menus_por_app.html
+│   ├── templatetags
+│   │   ├── __init__.py
+│   │   └── menus_tag.py
+│   ├── __init__.py
+│   ├── admin.py
+│   ├── apps.py
+│   ├── models.py
+│   ├── tests.py
+│   ├── urls.py
+│   └── views.py
+├── menusapp
+│   ├── __init__.py
+│   ├── settings.py
+│   ├── urls.py
+│   └── wsgi.py
+└── manage.py
+
+

Espero que tenham gostado, críticas e sugestões são bem-vindas. Fontes do Projeto

+

+
+ + +
+
+

Translations:

+
    +
+
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/drafts/menu-dinamico-com-apps-do-django-pt.html.gz b/drafts/menu-dinamico-com-apps-do-django-pt.html.gz new file mode 100644 index 000000000..cdde6585e Binary files /dev/null and b/drafts/menu-dinamico-com-apps-do-django-pt.html.gz differ diff --git a/drafts/my-azure-data-fundamentals-certification.html b/drafts/my-azure-data-fundamentals-certification.html new file mode 100644 index 000000000..478e8687c --- /dev/null +++ b/drafts/my-azure-data-fundamentals-certification.html @@ -0,0 +1,537 @@ + + + + + + + + My Experience with Azure Data Fundamentals certification - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+ + +
+

+
+ + +
+
+

Translations:

+ +
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/drafts/my-azure-data-fundamentals-certification.html.gz b/drafts/my-azure-data-fundamentals-certification.html.gz new file mode 100644 index 000000000..9c8fe1a28 Binary files /dev/null and b/drafts/my-azure-data-fundamentals-certification.html.gz differ diff --git a/drafts/pages/businesscard.html b/drafts/pages/businesscard.html new file mode 100644 index 000000000..8ae940877 --- /dev/null +++ b/drafts/pages/businesscard.html @@ -0,0 +1,304 @@ + + + + + + + + businesscard - Sipmann + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+

businesscard

+ +
+

Todo

+
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/drafts/pages/businesscard.html.gz b/drafts/pages/businesscard.html.gz new file mode 100644 index 000000000..719ba4d06 Binary files /dev/null and b/drafts/pages/businesscard.html.gz differ diff --git a/drafts/pages/services.html b/drafts/pages/services.html new file mode 100644 index 000000000..f5f988793 --- /dev/null +++ b/drafts/pages/services.html @@ -0,0 +1,304 @@ + + + + + + + + Services - Sipmann + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+

Services

+ +
+

Testing

+
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/drafts/pages/services.html.gz b/drafts/pages/services.html.gz new file mode 100644 index 000000000..215bd761b Binary files /dev/null and b/drafts/pages/services.html.gz differ diff --git a/drafts/pages/servicos-pt.html b/drafts/pages/servicos-pt.html new file mode 100644 index 000000000..33791d47c --- /dev/null +++ b/drafts/pages/servicos-pt.html @@ -0,0 +1,304 @@ + + + + + + + + Serviços - Sipmann + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+

Serviços

+ +
+

Testes

+
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/drafts/pages/servicos-pt.html.gz b/drafts/pages/servicos-pt.html.gz new file mode 100644 index 000000000..fd80d24b7 Binary files /dev/null and b/drafts/pages/servicos-pt.html.gz differ diff --git a/drafts/schedule-blog-post-with-powershell-and-pelican.html b/drafts/schedule-blog-post-with-powershell-and-pelican.html new file mode 100644 index 000000000..cba0a2873 --- /dev/null +++ b/drafts/schedule-blog-post-with-powershell-and-pelican.html @@ -0,0 +1,544 @@ + + + + + + + + Scheduling blog posts with Powershell and Pelican - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Scheduling blog posts with Powershell and Pelican

+
+ +
+
+ +
+

Hy folks, first time posting here on dev.to :). Recently I've been migrating some of my scripts from bash to PowerShell and I thought that would be a good time to code an automation script to publish posts on my personal blog. I host my blog with Github Pages and I use Pelican as a static site generator. The main problem I have with this toolkit, is the lack of scheduling posts. For those who are new to Pelican, the post system is similar to dev.to, we write the posts using Markdown and we have a Status tag to tell when the post is a draft or not.

+

The main idea of my script is, run through the Markdown files an check those who have Draft as status. Once I found any post, I start getting some info like the Date and the Slug. The Date part is a little tricky because we need to find the line, split the text and then parse it to do date comparisons. If the post date is lower then the current timespan I replace the Status: Draft tag and save the file. After that all we have to do is commit to git and let it go.

+
$postsPath = "E:\projetos\sipmann.github.io\content\";
+$files = Get-ChildItem $postsPath -File -Filter *.md
+
+<# Get the current datetime so we can compare with the psot date #>
+$now = Get-Date
+
+<# Set the current location, with this we can work with the git commands #>
+Set-Location $postsPath
+
+foreach($file in $files) {
+
+    <# Get's only posts with draft status #>
+    $isDraft = Get-Content ($postsPath + $file) | Where-Object { $_ -ccontains "Status: Draft" }
+
+    if ($isDraft) {
+
+        <# First we find the line with the date, then we get only the datetime and then parse it #>
+        $pubDate = [datetime]::parseexact(((Get-Content ($postsPath + $file) | Where-Object { $_ -Match "^Date:*" }) -split '\s+', 2)[1], 'yyyy-MM-dd HH:mm', $null)
+
+        <# TODO: Maybe call google and bing api to submit a new url #>
+        $slug = ((Get-Content ($postsPath + $file) | Where-Object { $_ -Match "^Slug:*" }) -split '\s+', 2)[1]
+
+        if ($now -ge $pubDate) {
+
+            <# Sets the content without the Draft status #>
+            ((Get-Content ($postsPath + $file)) -replace 'Status: Draft', '') | Set-Content ($postsPath + $file)
+
+            git add .
+            git commit -m ("New scheduled post: " + $file)
+            git push origin master
+        }
+    }
+}
+
+ +

Hope you find the script useful, and if you are interested in the other scripts I'm making with PowerShell, take a look at my github repo, still lacks many of my scripts, but it's there where I'll keep them updated. See ya.

+
+ + +
+
+

Translations:

+
    +
+
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/drafts/schedule-blog-post-with-powershell-and-pelican.html.gz b/drafts/schedule-blog-post-with-powershell-and-pelican.html.gz new file mode 100644 index 000000000..a402b45ac Binary files /dev/null and b/drafts/schedule-blog-post-with-powershell-and-pelican.html.gz differ diff --git a/drafts/script-de-inicializacao-raspberry-pt.html b/drafts/script-de-inicializacao-raspberry-pt.html new file mode 100644 index 000000000..870eee2bb --- /dev/null +++ b/drafts/script-de-inicializacao-raspberry-pt.html @@ -0,0 +1,571 @@ + + + + + + + + Scripts de inicialização no raspberry pi - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Scripts de inicialização no raspberry pi

+
+ +
+
+ +
+

Instalei essa semana o gitea no meu raspberry pi B + e queria iniciar ele no boot... Não sou profundo conhecedor de linux, então, logo não sabia como fazer isto da melhor forma. +As versões atuais do Raspbian utilizam o systemd para gerenciar os serviços e confesso que nunca havia utilizado o systemctl para nada.

+

Vamos começa criando um arquivo de serviço dentro da pasta /etc/systemd/system, vale ressaltar que a pasta system deve (em teoria) ser reservada para pacotes do sistema. +Vamos criar o arquivo com o nome gitea.service dentro da pasta antes mencionada. Abaixo podemos ver como ficou o arquivo e um detalhamento após ele.

+
[Unit]
+Description=Gitea Service
+After=network.target
+
+[Service]
+Type=simple
+User=root
+WorkingDirectory=/root/
+ExecStart=/root/gitea web
+Restart=on-abort
+
+

A composição do arquivo é bem simples, mas vamos a alguns detalhes. Type possui várias opções (simple, forking, oneshot), utilizamos simple uma vez que o nosso processo executara, permanecerá rodando e não executa um fork de processo. +Fork como acabo de comentar, deve ser utilizado caso o processo que for executando disparar mais processos. User irá definir o usuário do processo. WorkingDirectory definira onde o processo terá a sua base de execução, como o gitea esta localizada na pasta root, +aponto para lá. O ExecStart é bem simples e direto, deve chamar a execução do processo passando parametros caso seja necessário. O Restart é o que nos garantirá que o serviço permanecerá rodando caso haja algum imprevisto (exceto o fato de um usuário chamar o stop).

+

Salve o arquivo e vamos rodar um refresh para o SO perceber o novo serviço. Assim rodamos systemctl daemon-reload. Sempre que alterarmos um serviço ou criarmos um novo, este comando deve ser executado, caso contrário o próprio systemctl pode lhe alertar da necessidade. +Após reacarregar os serviços, vamos habilitar o serviço que criamos rodando systemctl enable gitea, feito isto temos alguns comandos uteis.

+
    +
  • systemctl start gitea
  • +
  • systemctl stop gitea
  • +
  • systemctl status gitea
  • +
+

O comando de status pode ser visto como exemplo abaixo.

+
● gitea.service - Gitea Service
+  Loaded: loaded (/etc/systemd/system/gitea.service; enabled; vendor preset: enabled)
+  Active: active (running) since Wed 2017-10-04 00:37:34 UTC; 52min ago
+Main PID: 1087 (gitea)
+  CGroup: /system.slice/gitea.service
+          └─1087 /root/gitea web
+
+Oct 04 00:38:31 gitserver gitea[1087]: [Macaron] 2017-10-04 00:38:31: Completed /explore/users 200 OK in 80.106173ms
+Oct 04 00:38:31 gitserver gitea[1087]: [Macaron] 2017-10-04 00:38:31: Started GET /img/favicon.png for 192.168.1.4
+Oct 04 00:38:31 gitserver gitea[1087]: [Macaron] [Static] Serving /img/favicon.png
+
+

Após estes processos, você pode reiniciar seu raspberry que o gitea irá subir e funcionar. Ressalto que, preste atenção tanto no WorkingDirectory quanto no ExecStart, no caso do gitea, ele utiliza o workingdir e a forma de start para saber onde irá largar os arquivos por padrão, então ou você configura ele com caminhos absolutos ou cuidar na forma de start (ao menos é o que consegui pegar até agora).

+

+
+ + +
+
+

Translations:

+
    +
+
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/drafts/script-de-inicializacao-raspberry-pt.html.gz b/drafts/script-de-inicializacao-raspberry-pt.html.gz new file mode 100644 index 000000000..10ca62b58 Binary files /dev/null and b/drafts/script-de-inicializacao-raspberry-pt.html.gz differ diff --git a/en/apache-nifi-json-to-sql-replacing-underscore.html b/en/apache-nifi-json-to-sql-replacing-underscore.html new file mode 100644 index 000000000..a596bf0a3 --- /dev/null +++ b/en/apache-nifi-json-to-sql-replacing-underscore.html @@ -0,0 +1,412 @@ + + + + + + + + Apache Nifi JSON to SQL Replacing underscore - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Apache Nifi JSON to SQL Replacing underscore

+
+ +
+
+ +
+

Recently I was doing some ETL with Apache NiFi. But after a few minutes of drawing my flow, I saw that the component ConvertJSONToSQL was replacing the underscore ('_') from the field name in the where condition (I was preparing an Update SQL). That was weird because, at the set statement, the field name was kept intact. After some research, I found that the property (see bellow) Translate Field Names was responsible for that weird replacement.

+

Apache NiFi JSONToSQL config

+

Before setting it to FALSE, be aware that the properties on your JSON data must match exactly the name of your fields.

+
+ + +
+
+

Translations:

+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/apache-nifi-json-to-sql-replacing-underscore.html.gz b/en/apache-nifi-json-to-sql-replacing-underscore.html.gz new file mode 100644 index 000000000..7cc9cdbe8 Binary files /dev/null and b/en/apache-nifi-json-to-sql-replacing-underscore.html.gz differ diff --git a/en/archives.html b/en/archives.html new file mode 100644 index 000000000..a9b23366e --- /dev/null +++ b/en/archives.html @@ -0,0 +1,358 @@ + + + + + + + + Sipmann - Archives + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+

Archives for Sipmann

+ +
+
Mon 21 December 2020
+
Monitoring MySQL restarts with PowerShell
+
Wed 09 December 2020
+
Changing a MySQL user password across multiple application instances without downtime
+
Wed 02 December 2020
+
Apache Nifi JSON to SQL Replacing underscore
+
Sat 14 November 2020
+
Blocking a user on SQL Server based on a schedule
+
Wed 28 October 2020
+
How to set columns on select using Entity Framework
+
Tue 20 October 2020
+
Zabbix Running on Low Memory Mode
+
Wed 14 October 2020
+
Monitoring MySQL Replication Status with PowerShell
+
Sat 03 October 2020
+
Microsoft Against Covid
+
Mon 21 September 2020
+
The power of PowerShell
+
Wed 29 July 2020
+
Top Level Statement in C# 9
+
Thu 02 July 2020
+
Zabbix poller processes more than 75%
+
Mon 22 June 2020
+
Monitoring a Website heath with Azure Functions
+
Tue 09 June 2020
+
Azure Data Fundamentals certification with 80% discount
+
Mon 25 May 2020
+
Zabbix ICMP pinger processes more than 75%
+
Thu 27 February 2020
+
Zabbix Server Out of Memory
+
Thu 03 October 2019
+
Flutter + firebase auth crashing
+
Fri 06 September 2019
+
Removing a user from SQL Server database who owns a schema
+
Mon 12 August 2019
+
Limiting Connection Resources on SQL Server
+
Tue 30 July 2019
+
Using git hooks to easy your life
+
Fri 13 April 2018
+
Microservices with NodeJS, Express.js and RabbitMQ Part 2
+
Wed 04 April 2018
+
Microservices with NodeJS, Express.js and RabbitMQ Part 1
+
Thu 29 March 2018
+
Connecting to a database through SSH
+
Sat 24 March 2018
+
Now posting on Grepora
+
Sat 17 March 2018
+
Scaffolding a React app with Parcel and Yeoman
+
Fri 09 March 2018
+
Could not open connection with MySQL and Hibernate
+
Sun 04 March 2018
+
Solving java.net.SocketException: Protocol family unavailable on a Java + Docker + WildFly
+
Tue 27 February 2018
+
Change display settings on linux with Disper
+
Sat 17 February 2018
+
Java - Files.readAllBytes throws OutOfMemory
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/archives.html.gz b/en/archives.html.gz new file mode 100644 index 000000000..40b87b0f0 Binary files /dev/null and b/en/archives.html.gz differ diff --git a/en/author/mauricio-camargo-sipmann.html b/en/author/mauricio-camargo-sipmann.html new file mode 100644 index 000000000..996a0f49e --- /dev/null +++ b/en/author/mauricio-camargo-sipmann.html @@ -0,0 +1,603 @@ + + + + + + + + Sipmann - Articles by Maurício Camargo Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+ +
+
+
+

Apache Nifi JSON to SQL Replacing underscore

+
+ +
+
+ +
+

Recently I was doing some ETL with Apache NiFi. But after a few minutes of drawing my flow, I saw that the component ConvertJSONToSQL was replacing the underscore ('_') from the field name in the where condition (I was preparing an Update SQL). That was weird because, at the set …

+
+ + + +
+
+
+
+ +
+
+ + + + + + + +
+

So, you use Entity Framework Core, and you usually code your selects like the following, maybe you are getting too much data.

+
var products = Products
+    .Where(p => p.UnitsInStock > 0)
+    .OrderBy(p => p.ProductName)
+    .ToList()
+
+ +

Running the query above, on my table, you'll get the following output, take a look …

+
+ + + +
+
+
+
+
+ + + + + +
+

Zabbix Running on Low Memory Mode

+
+ +
+
+ +
+

Hey folks, another Zabbix post today. This one it's about increasing the Zabbix Server Cache. It's pretty common (if you have the default settings only) get a warning about your Zabbix value cache running on low memory mode at your dashboard or logs.

+

Zabbix Dashboard warning about the memory problem +Zabbix Dashboard cache graph 70% used

+

To solve, go back to your Zabbix …

+
+ + + +
+
+
+
+
+ + + + + + + +
+

I've been migration some bash scripts that I have to PowerShell, and it's time to migrate a script that monitors the replication of a MySQL database. The credit for the original script goes to Paweł. It's a simple script where I seek a few tags/fields that we get from …

+
+ + + +
+
+
+
+
+
+

Microsoft Against Covid

+
+ +
+
+ +
+

Has your job been affected by covid? Well, last week I've posted on Grepora about a Free Certification Voucher that Microsoft was giving away at the Microsoft Ignite event. After that, I found that they were also giving a huge discount to people who have had their job affected by …

+
+ + + +
+
+
+
+
+ + + + + +
+

The power of PowerShell

+
+ +
+
+ +
+

As a long time Linux user, I've automated a few things with bash scripts and stayed away from PowerShell... I've moved to a Windows environment a few years ago and still, haven gave a shot to PS. But why not? I've made a few scripts to automate some tasks at …

+
+ + + +
+
+
+
+
+ + + + + +
+

Top Level Statement in C# 9

+
+ +
+
+ +
+

Hey folks, I'm coming along to tell you a few things about the new feature of C# 9. Every time you want to start a new project, you always have the same Main File, with the same structure. At the next version of C# (version 9), we'll have a new …

+
+ + + +
+
+
+
+
+ + 1 + 2 + 3 + » + +
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/author/mauricio-camargo-sipmann.html.gz b/en/author/mauricio-camargo-sipmann.html.gz new file mode 100644 index 000000000..b9d0a085d Binary files /dev/null and b/en/author/mauricio-camargo-sipmann.html.gz differ diff --git a/en/author/mauricio-camargo-sipmann2.html b/en/author/mauricio-camargo-sipmann2.html new file mode 100644 index 000000000..a0bd3d1d9 --- /dev/null +++ b/en/author/mauricio-camargo-sipmann2.html @@ -0,0 +1,582 @@ + + + + + + + + Sipmann - Articles by Maurício Camargo Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Zabbix poller processes more than 75%

+
+ +
+
+ +
+

Hey folks, this is the third post about tweaking the Zabbix configurations. All changes that I've suggested here were based on a Zabbix Server with 50+ hosts. Another thing that can happen to your server, it's the poller get overwhelmed by the amount of servers that need to be polled …

+
+ + + +
+
+
+
+
+ + + + + + + +
+

Sometimes you get your self in need to monitor a website's health or it's content for changes. Of course, there's plenty of options out there, but for the sake of curiosity, let's code our own to see what we can do. First things first. Everything you'll see here, you can …

+
+ + + +
+
+
+
+
+ + + + + + + +
+

Hey folks, if you want to achieve some certification this year, keep an eye open for vouchers. A few months ago, Oracle released a set of free courses with certifications. Now it's Microsoft time. Microsoft is updating they're certifications and we have a voucher of 80% discount using the coupon …

+
+ + + +
+
+
+
+
+
+

Zabbix ICMP pinger processes more than 75%

+
+ +
+
+ +
+

So your monitoring sytems have grown and your zabbix started loggin "Zabbix icmp pinger processes more than 75% busy" at the dashboard.

+

Dashboard do zabbix avisando sobre o erro

+

All you have to do is open your config file (/etc/zabbix/zabbix_server.conf) and find the a tag named StartPingers. It'll be commented by default. Uncomment it …

+
+ + + +
+
+
+
+
+
+

Zabbix Server Out of Memory

+
+ +
+
+ +
+

Do you have a crashing Zabbix Server and looking through the log /var/log/zabbix/zabbix_server.log you see the following out of memory message?

+
__mem_malloc: skipped 0 asked 24 skip_min 18446744073709551615 skip_max 0
+[file:dbconfig.c,line:94] __zbx_mem_realloc(): out of memory (requested 16 bytes)
+[file:dbconfig.c,line …

+
+ + + +
+
+
+
+
+
+

Flutter + firebase auth crashing

+
+ +
+
+ +
+

Hey Folks, recently I've started learning Flutter and right after a TODO List, I tried a Firebase integration. But as soon as I started setting the dependencies, my app stopped opening... just a crash. After a few logs digging, I've found the following log.

+
AndroidRuntime: FATAL EXCEPTION: main
+AndroidRuntime: Process …

+
+ + + +
+
+
+
+
+ + +
+

Your customer urge you to drop a user from the MsSQL Server database, but you stuck with the following related error:

+
Error: 15138 The database principal owns a schema in the database, and cannot be dropped.
+
+ +

That means that the user owns one or more shcemas of your database. If …

+
+ + + +
+
+
+
+
+ + + + + +
+

Limiting Connection Resources on SQL Server

+
+ +
+
+ +
+

Have you ever suffered from a slow SQLServer database? Someone love to run that heavy query in the database? Resource Governor to the rescue. You can set a few rules on how users (connections actually) will use the server/database resources based on a few things.

+

First things first, if …

+
+ + + +
+
+
+
+
+
+

Using git hooks to easy your life

+
+ +
+
+ +
+

Hey folks, it's been a time since my last post. In the meantime, I moved to another state, changed job, and started learning new kinds of stuff. Today I would like to share one thing that I usually do with my small git projects. Git has many cool features, git …

+
+ + + +
+
+
+
+ +
+
+ « + + 1 + 2 + 3 + » + +
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/author/mauricio-camargo-sipmann2.html.gz b/en/author/mauricio-camargo-sipmann2.html.gz new file mode 100644 index 000000000..7dd70c988 Binary files /dev/null and b/en/author/mauricio-camargo-sipmann2.html.gz differ diff --git a/en/author/mauricio-camargo-sipmann3.html b/en/author/mauricio-camargo-sipmann3.html new file mode 100644 index 000000000..1b98b7706 --- /dev/null +++ b/en/author/mauricio-camargo-sipmann3.html @@ -0,0 +1,526 @@ + + + + + + + + Sipmann - Articles by Maurício Camargo Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+ + + + + + + +
+

This is the first part of a microservices development series. The service will consist of the bellow architecture, where we will expose an image optimizer service that will forward the request to a RabbitMQ queue and answer with the bytecode of the optimized image. It shouldn't be a long series …

+
+ + + +
+
+
+
+
+
+

Connecting to a database through SSH

+
+ +
+
+ +
+

If someday, for some reason, you need to establish a connection with a database which is behind a firewall and you only have SSH access on that server (and you don't want to use a CLI) you can do an SSH tunnel. It's pretty simple, bellow has a sample of …

+
+ + + +
+
+
+
+
+
+

Now posting on Grepora

+
+ +
+
+ +
+

A few weeks ago I started posting at Grepora blog. If you like or are looking for some Oracle related stuff, Grepora it's a good place to go and spend a time reading :). From time to time I'll be posting there, it doesn't mean that this blog will be closed …

+
+ + + +
+
+
+
+
+ + + + + + + +
+

Since Parcel JS arrived, I've been using it a lot as an awesome alternative for WebPack. Webpack isn't bad but IMO it's too complex for the job and parcel do the same (at least the basic) with almost zero configuration. But if you need to create many apps (like a …

+
+ + + +
+
+
+
+
+ + + + + + + +
+

Last day I decided to deploy a MySQL Docker image to work with my Java application. I've been using PostgreSQL instead and have no problems at all, but after I moved to MySQL, the app didn't connect anymore with the database and throw some "Could not open connection" at my …

+
+ + + +
+
+
+
+ +
+
+ + + + + +
+

Change display settings on linux with Disper

+
+ +
+
+ +
+

From time to time, I change the Linux distro on my laptop or just do a fresh install on it. And once in a while, have random problems with external displays. It can be something really "simple" like don't detecting the external monitor or something crazy like the image below …

+
+ + + +
+
+
+
+
+
+

Java - Files.readAllBytes throws OutOfMemory

+
+ +
+
+ +
+

When you need to interact with files, there's the possibility to read all bytes from the file with Files.readAllBytes. But be aware of the kinds of files your application will deal with because the Java API files have a limit for the buffer that is defined as Integer.MAX_VALUE …

+
+ + + +
+
+
+
+
+ « + + 1 + 2 + 3 + +
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/author/mauricio-camargo-sipmann3.html.gz b/en/author/mauricio-camargo-sipmann3.html.gz new file mode 100644 index 000000000..abc4fe484 Binary files /dev/null and b/en/author/mauricio-camargo-sipmann3.html.gz differ diff --git a/en/authors.html b/en/authors.html new file mode 100644 index 000000000..685ae4b29 --- /dev/null +++ b/en/authors.html @@ -0,0 +1,302 @@ + + + + + + + + Sipmann - Authors + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+

Authors on Sipmann

+ +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/authors.html.gz b/en/authors.html.gz new file mode 100644 index 000000000..6bf665eed Binary files /dev/null and b/en/authors.html.gz differ diff --git a/en/azure-data-fundamentals-certification-80-discount.html b/en/azure-data-fundamentals-certification-80-discount.html new file mode 100644 index 000000000..13191eae2 --- /dev/null +++ b/en/azure-data-fundamentals-certification-80-discount.html @@ -0,0 +1,512 @@ + + + + + + + + Azure Data Fundamentals certification with 80% discount - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+ + +
+

Hey folks, if you want to achieve some certification this year, keep an eye open for vouchers. A few months ago, Oracle released a set of free courses with certifications. Now it's Microsoft time. Microsoft is updating they're certifications and we have a voucher of 80% discount using the coupon DP900Norfolk at the checkout of the beta certification DP-900.

+

Be aware that this certification is in beta and the result won't be instantly available as the regular ones. Access the following link and schedule your exam. https://docs.microsoft.com/pt-br/learn/certifications/exams/dp-900.

+

Update: There is a 80% voucher also for https://docs.microsoft.com/en-us/learn/certifications/azure-ai-fundamentals. Voucher: AI900Saratoga

+
+ + +
+
+

Translations:

+
    +
+
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/azure-data-fundamentals-certification-80-discount.html.gz b/en/azure-data-fundamentals-certification-80-discount.html.gz new file mode 100644 index 000000000..b03373f9d Binary files /dev/null and b/en/azure-data-fundamentals-certification-80-discount.html.gz differ diff --git a/en/blocking-user-on-sql-server-based-on-schedule.html b/en/blocking-user-on-sql-server-based-on-schedule.html new file mode 100644 index 000000000..bbe058229 --- /dev/null +++ b/en/blocking-user-on-sql-server-based-on-schedule.html @@ -0,0 +1,567 @@ + + + + + + + + Blocking a user on SQL Server based on a schedule - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Blocking a user on SQL Server based on a schedule

+
+ +
+
+ +
+

Ok, some time ago, I've posted about how you can set limits to connections on SQL Server using the Resource Governor. But what if you can't use it? You always can block logins using a login trigger, but I don't like the idea of having selects running on every login. So I came across with a solution using a stored procedure, a table and the Agent.

+

The main idea is, store the time that a user must be blocked and using the Agent, disable or enable the user. Bellow you can see the table (the table is in Portuguese, but I have a few comment blocks to help you).

+
CREATE TABLE dbo.HorariosBloqueio (
+    Id INT NOT NULL,
+    LoginName NVARCHAR(100) NOT NULL,
+    HrInicio TIME NOT NULL, /* Startint block time */
+    HrTermino TIME NOT NULL, /* Ending block time */
+    Bloqueado INT DEFAULT 0, /* 0 = unblocked, 1 = blocked */
+    PRIMARY KEY (Id)
+);
+GO
+
+/* Don't block the SA user, precautions, you know */
+ALTER TABLE dbo.HorariosBloqueio
+    ADD CONSTRAINT chk_users CHECK (LoginName not in ('sa'));
+
+ALTER TABLE dbo.HorariosBloqueio
+    ADD CONSTRAINT chk_hora_final_maior CHECK (HrTermino > HrInicio);
+
+ALTER TABLE dbo.HorariosBloqueio
+    ADD CONSTRAINT chk_status_bloqueio CHECK (Bloqueado in (0, 1));
+
+CREATE SEQUENCE dbo.seq_HorariosBloqueio START WITH 1 INCREMENT BY 1;
+GO
+
+ +

After creating the table, let's check the procedure that will handle the enabling/disabling the users. Be aware that on the procedure, I've set the database name where the table was stored, you can change it replacing the DBATOOLS text to the database name where you created the table.

+
IF OBJECT_ID('dbo.sp_ValidarLogin') IS NULL
+  EXEC ('CREATE PROCEDURE dbo.sp_ValidarLogin AS RETURN 0;');
+GO
+
+CREATE OR ALTER PROC dbo.sp_ValidarLogin
+AS BEGIN
+    DECLARE @LoginName AS NVARCHAR(100);
+    DECLARE @Momento AS TIME;
+    SET @Momento = CAST(GETDATE() AS TIME);
+
+    /* Block the ones that aren't blocked already and maches the time */
+    DECLARE block_cursor CURSOR
+        FOR SELECT LoginName FROM [DBATOOLS].[dbo].[HorariosBloqueio] WHERE Bloqueado = 0 AND HrInicio <= @Momento AND HrTermino >= @Momento
+    OPEN block_cursor;
+
+    FETCH NEXT FROM block_cursor INTO @LoginName
+
+    WHILE @@FETCH_STATUS = 0
+    BEGIN
+        exec ('ALTER LOGIN ' + @LoginName + ' DISABLE;');
+
+        print 'Bloqued usuario ' + @LoginName;
+
+        FETCH NEXT FROM block_cursor INTO @LoginName
+    END;
+
+    CLOSE block_cursor;
+    DEALLOCATE block_cursor;
+
+    UPDATE [DBATOOLS].[dbo].[HorariosBloqueio] SET Bloqueado = 1 WHERE HrInicio <= @Momento AND HrTermino >= @Momento
+
+
+    /* Enable up who was blocked */
+    DECLARE unblock_cursor CURSOR
+        FOR SELECT LoginName FROM [DBATOOLS].[dbo].[HorariosBloqueio] WHERE Bloqueado = 1 AND (HrInicio > @Momento OR HrTermino < @Momento)
+    OPEN unblock_cursor ;
+
+    FETCH NEXT FROM unblock_cursor  INTO @LoginName
+
+    WHILE @@FETCH_STATUS = 0
+    BEGIN
+        exec ('ALTER LOGIN ' + @LoginName +' ENABLE;');
+
+        print 'Unbloqued usuario ' + @LoginName;
+
+        FETCH NEXT FROM unblock_cursor  INTO @LoginName
+    END;
+
+    CLOSE unblock_cursor;
+    DEALLOCATE unblock_cursor;
+
+    UPDATE [DBATOOLS].[dbo].[HorariosBloqueio] SET Bloqueado = 0 WHERE Bloqueado = 1 AND (HrInicio > @Momento OR HrTermino < @Momento)
+END;
+
+ +

Ok, so now all you have to do, is schedule a job to run that stored procedure from minute to minute. Again, the main idea is tell the procedure when a user must be blocked and when it'll be unblocked.

+
    -- Will block the user protheus from 10 AM till 15 PM
+    INSERT INTO dbo.HorariosBloqueio (Id, LoginName, HrInicio, HrTermino) VALUES (NEXT VALUE FOR seq_HorariosBloqueio, 'protheus', '10:00:00', '15:00:00');
+

+
+ + +
+
+

Translations:

+ +
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/blocking-user-on-sql-server-based-on-schedule.html.gz b/en/blocking-user-on-sql-server-based-on-schedule.html.gz new file mode 100644 index 000000000..01fa97fed Binary files /dev/null and b/en/blocking-user-on-sql-server-based-on-schedule.html.gz differ diff --git a/en/categories.html b/en/categories.html new file mode 100644 index 000000000..57dcdafcf --- /dev/null +++ b/en/categories.html @@ -0,0 +1,312 @@ + + + + + + + + Sipmann - Categories + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+

Categories on Sipmann

+ +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/categories.html.gz b/en/categories.html.gz new file mode 100644 index 000000000..5fab86af3 Binary files /dev/null and b/en/categories.html.gz differ diff --git a/en/category/azure.html b/en/category/azure.html new file mode 100644 index 000000000..803891f13 --- /dev/null +++ b/en/category/azure.html @@ -0,0 +1,370 @@ + + + + + + + + Sipmann - Azure category + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Microsoft Against Covid

+
+ +
+
+ +
+

Has your job been affected by covid? Well, last week I've posted on Grepora about a Free Certification Voucher that Microsoft was giving away at the Microsoft Ignite event. After that, I found that they were also giving a huge discount to people who have had their job affected by …

+
+ + + +
+
+
+
+
+ + + + + + + +
+

Sometimes you get your self in need to monitor a website's health or it's content for changes. Of course, there's plenty of options out there, but for the sake of curiosity, let's code our own to see what we can do. First things first. Everything you'll see here, you can …

+
+ + + +
+
+
+
+
+ + + + + + + +
+

Hey folks, if you want to achieve some certification this year, keep an eye open for vouchers. A few months ago, Oracle released a set of free courses with certifications. Now it's Microsoft time. Microsoft is updating they're certifications and we have a voucher of 80% discount using the coupon …

+
+ + + +
+
+
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/category/azure.html.gz b/en/category/azure.html.gz new file mode 100644 index 000000000..330322271 Binary files /dev/null and b/en/category/azure.html.gz differ diff --git a/en/category/flutter.html b/en/category/flutter.html new file mode 100644 index 000000000..3bcf1ff53 --- /dev/null +++ b/en/category/flutter.html @@ -0,0 +1,304 @@ + + + + + + + + Sipmann - Flutter category + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Flutter + firebase auth crashing

+
+ +
+
+ +
+

Hey Folks, recently I've started learning Flutter and right after a TODO List, I tried a Firebase integration. But as soon as I started setting the dependencies, my app stopped opening... just a crash. After a few logs digging, I've found the following log.

+
AndroidRuntime: FATAL EXCEPTION: main
+AndroidRuntime: Process …

+
+ + + +
+
+
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/category/flutter.html.gz b/en/category/flutter.html.gz new file mode 100644 index 000000000..9352544f3 Binary files /dev/null and b/en/category/flutter.html.gz differ diff --git a/en/category/front-end.html b/en/category/front-end.html new file mode 100644 index 000000000..ee1f0dabd --- /dev/null +++ b/en/category/front-end.html @@ -0,0 +1,375 @@ + + + + + + + + Sipmann - Front-end category + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+ + + + + + + +
+

This is the first part of a microservices development series. The service will consist of the bellow architecture, where we will expose an image optimizer service that will forward the request to a RabbitMQ queue and answer with the bytecode of the optimized image. It shouldn't be a long series …

+
+ + + +
+
+
+
+
+ + + + + + + +
+

Since Parcel JS arrived, I've been using it a lot as an awesome alternative for WebPack. Webpack isn't bad but IMO it's too complex for the job and parcel do the same (at least the basic) with almost zero configuration. But if you need to create many apps (like a …

+
+ + + +
+
+
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/category/front-end.html.gz b/en/category/front-end.html.gz new file mode 100644 index 000000000..8c698cc04 Binary files /dev/null and b/en/category/front-end.html.gz differ diff --git a/en/category/java.html b/en/category/java.html new file mode 100644 index 000000000..32be986df --- /dev/null +++ b/en/category/java.html @@ -0,0 +1,370 @@ + + + + + + + + Sipmann - Java category + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+ + + + + + + +
+

Last day I decided to deploy a MySQL Docker image to work with my Java application. I've been using PostgreSQL instead and have no problems at all, but after I moved to MySQL, the app didn't connect anymore with the database and throw some "Could not open connection" at my …

+
+ + + +
+
+
+
+ +
+
+
+

Java - Files.readAllBytes throws OutOfMemory

+
+ +
+
+ +
+

When you need to interact with files, there's the possibility to read all bytes from the file with Files.readAllBytes. But be aware of the kinds of files your application will deal with because the Java API files have a limit for the buffer that is defined as Integer.MAX_VALUE …

+
+ + + +
+
+
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/category/java.html.gz b/en/category/java.html.gz new file mode 100644 index 000000000..cd5fc3a1d Binary files /dev/null and b/en/category/java.html.gz differ diff --git a/en/category/linux.html b/en/category/linux.html new file mode 100644 index 000000000..b62b8e681 --- /dev/null +++ b/en/category/linux.html @@ -0,0 +1,460 @@ + + + + + + + + Sipmann - Linux category + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+ + + + + +
+

Zabbix Running on Low Memory Mode

+
+ +
+
+ +
+

Hey folks, another Zabbix post today. This one it's about increasing the Zabbix Server Cache. It's pretty common (if you have the default settings only) get a warning about your Zabbix value cache running on low memory mode at your dashboard or logs.

+

Zabbix Dashboard warning about the memory problem +Zabbix Dashboard cache graph 70% used

+

To solve, go back to your Zabbix …

+
+ + + +
+
+
+
+
+
+

Zabbix poller processes more than 75%

+
+ +
+
+ +
+

Hey folks, this is the third post about tweaking the Zabbix configurations. All changes that I've suggested here were based on a Zabbix Server with 50+ hosts. Another thing that can happen to your server, it's the poller get overwhelmed by the amount of servers that need to be polled …

+
+ + + +
+
+
+
+
+
+

Zabbix ICMP pinger processes more than 75%

+
+ +
+
+ +
+

So your monitoring sytems have grown and your zabbix started loggin "Zabbix icmp pinger processes more than 75% busy" at the dashboard.

+

Dashboard do zabbix avisando sobre o erro

+

All you have to do is open your config file (/etc/zabbix/zabbix_server.conf) and find the a tag named StartPingers. It'll be commented by default. Uncomment it …

+
+ + + +
+
+
+
+
+
+

Zabbix Server Out of Memory

+
+ +
+
+ +
+

Do you have a crashing Zabbix Server and looking through the log /var/log/zabbix/zabbix_server.log you see the following out of memory message?

+
__mem_malloc: skipped 0 asked 24 skip_min 18446744073709551615 skip_max 0
+[file:dbconfig.c,line:94] __zbx_mem_realloc(): out of memory (requested 16 bytes)
+[file:dbconfig.c,line …

+
+ + + +
+
+
+
+
+
+

Connecting to a database through SSH

+
+ +
+
+ +
+

If someday, for some reason, you need to establish a connection with a database which is behind a firewall and you only have SSH access on that server (and you don't want to use a CLI) you can do an SSH tunnel. It's pretty simple, bellow has a sample of …

+
+ + + +
+
+
+
+
+ + + + + +
+

Change display settings on linux with Disper

+
+ +
+
+ +
+

From time to time, I change the Linux distro on my laptop or just do a fresh install on it. And once in a while, have random problems with external displays. It can be something really "simple" like don't detecting the external monitor or something crazy like the image below …

+
+ + + +
+
+
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/category/linux.html.gz b/en/category/linux.html.gz new file mode 100644 index 000000000..bac000e9c Binary files /dev/null and b/en/category/linux.html.gz differ diff --git a/en/category/mysql.html b/en/category/mysql.html new file mode 100644 index 000000000..d2cb6f512 --- /dev/null +++ b/en/category/mysql.html @@ -0,0 +1,307 @@ + + + + + + + + Sipmann - MySQL category + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/category/mysql.html.gz b/en/category/mysql.html.gz new file mode 100644 index 000000000..4159f20f1 Binary files /dev/null and b/en/category/mysql.html.gz differ diff --git a/en/category/net.html b/en/category/net.html new file mode 100644 index 000000000..37b29277a --- /dev/null +++ b/en/category/net.html @@ -0,0 +1,348 @@ + + + + + + + + Sipmann - .NET category + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+ + + + + + + +
+

So, you use Entity Framework Core, and you usually code your selects like the following, maybe you are getting too much data.

+
var products = Products
+    .Where(p => p.UnitsInStock > 0)
+    .OrderBy(p => p.ProductName)
+    .ToList()
+
+ +

Running the query above, on my table, you'll get the following output, take a look …

+
+ + + +
+
+
+
+
+ + + + + +
+

Top Level Statement in C# 9

+
+ +
+
+ +
+

Hey folks, I'm coming along to tell you a few things about the new feature of C# 9. Every time you want to start a new project, you always have the same Main File, with the same structure. At the next version of C# (version 9), we'll have a new …

+
+ + + +
+
+
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/category/net.html.gz b/en/category/net.html.gz new file mode 100644 index 000000000..43aac5f0f Binary files /dev/null and b/en/category/net.html.gz differ diff --git a/en/category/powershell.html b/en/category/powershell.html new file mode 100644 index 000000000..14fcc3b79 --- /dev/null +++ b/en/category/powershell.html @@ -0,0 +1,379 @@ + + + + + + + + Sipmann - PowerShell category + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+ + + + + + + +
+

I've been migration some bash scripts that I have to PowerShell, and it's time to migrate a script that monitors the replication of a MySQL database. The credit for the original script goes to Paweł. It's a simple script where I seek a few tags/fields that we get from …

+
+ + + +
+
+
+
+
+ + + + + +
+

The power of PowerShell

+
+ +
+
+ +
+

As a long time Linux user, I've automated a few things with bash scripts and stayed away from PowerShell... I've moved to a Windows environment a few years ago and still, haven gave a shot to PS. But why not? I've made a few scripts to automate some tasks at …

+
+ + + +
+
+
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/category/powershell.html.gz b/en/category/powershell.html.gz new file mode 100644 index 000000000..b7a71a4fa Binary files /dev/null and b/en/category/powershell.html.gz differ diff --git a/en/category/random.html b/en/category/random.html new file mode 100644 index 000000000..66d2f8f92 --- /dev/null +++ b/en/category/random.html @@ -0,0 +1,302 @@ + + + + + + + + Sipmann - Random category + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Now posting on Grepora

+
+ +
+
+ +
+

A few weeks ago I started posting at Grepora blog. If you like or are looking for some Oracle related stuff, Grepora it's a good place to go and spend a time reading :). From time to time I'll be posting there, it doesn't mean that this blog will be closed …

+
+ + + +
+
+
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/category/random.html.gz b/en/category/random.html.gz new file mode 100644 index 000000000..ea007bb49 Binary files /dev/null and b/en/category/random.html.gz differ diff --git a/en/category/sql-server.html b/en/category/sql-server.html new file mode 100644 index 000000000..cda0e386f --- /dev/null +++ b/en/category/sql-server.html @@ -0,0 +1,375 @@ + + + + + + + + Sipmann - SQL Server category + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+ + +
+

Your customer urge you to drop a user from the MsSQL Server database, but you stuck with the following related error:

+
Error: 15138 The database principal owns a schema in the database, and cannot be dropped.
+
+ +

That means that the user owns one or more shcemas of your database. If …

+
+ + + +
+
+
+
+
+ + + + + +
+

Limiting Connection Resources on SQL Server

+
+ +
+
+ +
+

Have you ever suffered from a slow SQLServer database? Someone love to run that heavy query in the database? Resource Governor to the rescue. You can set a few rules on how users (connections actually) will use the server/database resources based on a few things.

+

First things first, if …

+
+ + + +
+
+
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/category/sql-server.html.gz b/en/category/sql-server.html.gz new file mode 100644 index 000000000..b4cb764e6 Binary files /dev/null and b/en/category/sql-server.html.gz differ diff --git a/en/category/tools.html b/en/category/tools.html new file mode 100644 index 000000000..ba7f82ee5 --- /dev/null +++ b/en/category/tools.html @@ -0,0 +1,331 @@ + + + + + + + + Sipmann - Tools category + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Apache Nifi JSON to SQL Replacing underscore

+
+ +
+
+ +
+

Recently I was doing some ETL with Apache NiFi. But after a few minutes of drawing my flow, I saw that the component ConvertJSONToSQL was replacing the underscore ('_') from the field name in the where condition (I was preparing an Update SQL). That was weird because, at the set …

+
+ + + +
+
+
+
+
+
+

Using git hooks to easy your life

+
+ +
+
+ +
+

Hey folks, it's been a time since my last post. In the meantime, I moved to another state, changed job, and started learning new kinds of stuff. Today I would like to share one thing that I usually do with my small git projects. Git has many cool features, git …

+
+ + + +
+
+
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/category/tools.html.gz b/en/category/tools.html.gz new file mode 100644 index 000000000..50356f05a Binary files /dev/null and b/en/category/tools.html.gz differ diff --git a/en/cloud-not-open-connection-java-mysql-hibernate.html b/en/cloud-not-open-connection-java-mysql-hibernate.html new file mode 100644 index 000000000..9b1786b01 --- /dev/null +++ b/en/cloud-not-open-connection-java-mysql-hibernate.html @@ -0,0 +1,475 @@ + + + + + + + + Could not open connection with MySQL and Hibernate - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+ + +
+

Last day I decided to deploy a MySQL Docker image to work with my Java application. I've been using PostgreSQL instead and have no problems at all, but after I moved to MySQL, the app didn't connect anymore with the database and throw some "Could not open connection" at my face, but why? I've tried to connect to it manually and got the same problem.

+

After some research, I found that the true error should be java.sql.SQLException: null, message from server: "Host '172.17.0.4' is not allowed to connect to this MySQL server" but it wasn't showing to me...

+

After all, be aware that with the docker image MySQL:5.7.21 (latest version right now) the root user isn't allowed to remote connect to the database (it's alright, security reasons) and if you still want to do remote connections to it with root there are a few things you can do.

+
    +
  1. Create a user or allow root to access from other IPs.
  2. +
+
#No access to user root on any other IP
+SELECT User, Host FROM mysql.user;
++---------------+-----------+
+| User          | Host      |
++---------------+-----------+
+| healthchecker | localhost |
+| root          | localhost |
++---------------+-----------+
+2 rows in set (0.01 sec)
+
+CREATE USER 'newuser'@'%' IDENTIFIED BY 'password'; #% mean any IP
+GRANT ALL PRIVILEGES ON *.* TO 'newuser'@'%';   #*.* mean database.table ;)
+
+
    +
  1. Use MariaDB instead, witch come (at least on the version 10.2.13) with root allowed to do remote connections and will work like MySQL :)
  2. +
+

I changed to MariaDB as it work without creating user or any changes on the Java code or the docker run command.

+

+
+ + +
+
+

Translations:

+
    +
+
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/cloud-not-open-connection-java-mysql-hibernate.html.gz b/en/cloud-not-open-connection-java-mysql-hibernate.html.gz new file mode 100644 index 000000000..0e66ac7af Binary files /dev/null and b/en/cloud-not-open-connection-java-mysql-hibernate.html.gz differ diff --git a/en/connecting_to_database_through_ssh.html b/en/connecting_to_database_through_ssh.html new file mode 100644 index 000000000..ef1536ac0 --- /dev/null +++ b/en/connecting_to_database_through_ssh.html @@ -0,0 +1,464 @@ + + + + + + + + Connecting to a database through SSH - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Connecting to a database through SSH

+
+ +
+
+ +
+

If someday, for some reason, you need to establish a connection with a database which is behind a firewall and you only have SSH access on that server (and you don't want to use a CLI) you can do an SSH tunnel. It's pretty simple, bellow has a sample of how to allow connections to a remote Firebird database.

+
ssh -L 3051:192.168.1.9:3050 username@192.168.1.9
+
+

The -L parameter tells to SSH do a local port forwarding on local port 3051 to remote port 3050. You can use it to a connection with many services, not just databases.

+

You can do the reverse kind of tunnel, forward connections from the host to your local machine, you just have to change the parameter form "-L" to "-R" and the port order is inverted, first come the port where the server will listen and after your localhost port. This remote port forwarding must be enabled on the server. Look for GatewayPorts at the ssh config file.

+
ssh -R 3050:localhost:3050 username@192.168.1.9
+
+

Why whould you need something like that?? Let's say you want to share a localhost site/database with a friend, but your internet connection don't allow you to expose any port but you have access to a remote server witch can do that. Problem solved ;).

+

+
+ + +
+
+

Translations:

+
    +
+
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/connecting_to_database_through_ssh.html.gz b/en/connecting_to_database_through_ssh.html.gz new file mode 100644 index 000000000..d817957f3 Binary files /dev/null and b/en/connecting_to_database_through_ssh.html.gz differ diff --git a/en/drafts/cloud-not-open-connection-java-mysql-hibernate-pt.html b/en/drafts/cloud-not-open-connection-java-mysql-hibernate-pt.html new file mode 100644 index 000000000..218318592 --- /dev/null +++ b/en/drafts/cloud-not-open-connection-java-mysql-hibernate-pt.html @@ -0,0 +1,475 @@ + + + + + + + + Could not open connection com MySQL e Hibernate - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+ + +
+

Last day I decided to deploy a MySQL Docker image to work with my Java application. I've been using PostgreSQL instead and have no problems at all, but after I moved to MySQL, the app didn't connect anymore with the database and throw some "Could not open connection" at my face, but why? I've tried to connect to it manually and got the same problem.

+

After some research, I found that the true error should be java.sql.SQLException: null, message from server: "Host '172.17.0.4' is not allowed to connect to this MySQL server" but it wasn't showing to me...

+

After all, be aware that with the docker image MySQL:5.7.21 (latest version right now) the root user isn't allowed to remote connect to the database (it's alright, security reasons) and if you still want to do remote connections to it with root there are a few things you can do.

+
    +
  1. Create a user or allow root to access from other IPs.
  2. +
+
#No access to user root on any other IP
+SELECT User, Host FROM mysql.user;
++---------------+-----------+
+| User          | Host      |
++---------------+-----------+
+| healthchecker | localhost |
+| root          | localhost |
++---------------+-----------+
+2 rows in set (0.01 sec)
+
+CREATE USER 'newuser'@'%' IDENTIFIED BY 'password'; #% mean any IP
+GRANT ALL PRIVILEGES ON *.* TO 'newuser'@'%';   #*.* mean database.table ;)
+
+
    +
  1. Use MariaDB instead, witch come (at least on the version 10.2.13) with root allowed to do remote connections and will work like MySQL :)
  2. +
+

I changed to MariaDB as it work without creating user or any changes on the Java code or the docker run command.

+

+
+ + +
+
+

Translations:

+
    +
+
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/drafts/cloud-not-open-connection-java-mysql-hibernate-pt.html.gz b/en/drafts/cloud-not-open-connection-java-mysql-hibernate-pt.html.gz new file mode 100644 index 000000000..a7a76878c Binary files /dev/null and b/en/drafts/cloud-not-open-connection-java-mysql-hibernate-pt.html.gz differ diff --git a/en/drafts/cool-tools-pt.html b/en/drafts/cool-tools-pt.html new file mode 100644 index 000000000..860edf49b --- /dev/null +++ b/en/drafts/cool-tools-pt.html @@ -0,0 +1,457 @@ + + + + + + + + Cool Tools - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Cool Tools

+
+ +
+
+ +
+

Com o passar do tempo você vai "encontrando" - e às vezes até mesmo desenvolvendo - algumas ferramentas que tornam o seu dia a dia como desenvolvedor mais fácil. Abaixo seguem algumas das minhas ferramentas que costumo usar. Ressalto que essa lista será (provavelmente) atualizada com o passar do tempo.

+
+

https://www.gitkraken.com

+

Eu gosto muito de usar git, mas às vezes fico cansado de ter que usar só linha de comando, e achei no GitKreaken uma interface muito legal de se usar.

+
+
+

http://paletton.com

+

Toda vez que você vai fazer um novo sistema/site, ou até mesmo trocar o layout de algum já existente, você acaba tendo que montar uma paleta de cores para se utilizar em todo o template.

+
+
+

https://icomoon.io/app/#/select

+

Querendo usar ícones como fontes? Vá aí e gere apenas os arquivos que você vai realmente utilizar e economize alguns kbs.

+
+
+

https://syncthing.net/

+

Se você procura algum meio de sincronizar seus arquivos entre vários pcs e por algum motivo não quer usar um Google Drive ou DropBox, fica aqui a indicação deste cara.

+
+
+

http://sqitch.org/

+

Gerenciamento de versões de um banco de dados pode ser bem complicado e trabalhoso... Manter diversos ambientes (desenvolvimento, homologação, produção) vai dar um trabalho se não utilizar alguma ferramenta. Porque não usar o melhor de gerenciamento de versão (git) e uma ferramenta que se adequa ao que você precisa? sqitch é o cara nessas horas.

+
+
+

http://www.setupmyproject.com/

+

Preparação de projetos java, com frameworks, bibliotecas, nomenclatura, etc... Rende uma economia de tempo grandiosa e já vem tudo pronto :).

+
+
+

https://www.pexels.com/

+

Bom site para imagens free stock. Excelente local para conseguir imagens de alta qualidade.

+
+
+

https://heml.io/

+

"HEML is an open source markup language for building responsive email." Melhor descrição impossível.

+
+
+

https://www.mockapi.io/

+

Desenvolva mocks para testar seu front-end. Eles geram inclusive uma carga de dados para ser utilizado nos seus testes.

+
+
+

https://undraw.co

+

Needing some cool and free ilustrations? Take a look at it.

+
+
+

https://www.audiotool.com/app/

+

Ferramenta para criar sons, musicas e afins

+
+
+

https://app.cloudskew.com/

+

Desenhar projetos de cloud e afins

+
+
+

https://lottiefiles.com/

+

Veja por si mesmo

+
+

+
+ + +
+
+

Translations:

+
    +
+
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/drafts/cool-tools-pt.html.gz b/en/drafts/cool-tools-pt.html.gz new file mode 100644 index 000000000..6b87f3a48 Binary files /dev/null and b/en/drafts/cool-tools-pt.html.gz differ diff --git a/en/drafts/desenvolvendo-app-firefoxos-pt.html b/en/drafts/desenvolvendo-app-firefoxos-pt.html new file mode 100644 index 000000000..552b9fae3 --- /dev/null +++ b/en/drafts/desenvolvendo-app-firefoxos-pt.html @@ -0,0 +1,490 @@ + + + + + + + + Desenvolvendo apps para o FirefoxOS (Parte 1) - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Desenvolvendo apps para o FirefoxOS (Parte 1)

+
+ +
+
+ +
+

Requisitos mínimos?

+

Para seguir este tutorial você precisará do Nodejs. Utilizaremos ele para automatizar algumas tarefas, como a criação do nosso projeto e até mesmo o empacotamento da app. Estas automatizações se darão pela utilização de algumas aplicações como o Yeoman e o Grunt .

+

Também será necessário o emulador do FirefoxOS, ele roda através do seu navegador Firefox. Para instalá-lo basta ir no menu Ferramentas > Desenvolvedor web > App Manager, nesta tela basta tentar iniciar o emulador, se não possuir um já instalado, você será solicitado a fazê-lo. Neste tutorial irei utilizar a versão 1.4.

+

Preparando o ambiente

+

Tendo o Node instalado, vamos instalar o yeoman e o gerador de app para Firefox OS. Atenção para o parâmetro '-g' no processo de instalação, com ele os seus pacotes serão instalados globalmente, e não só para a pasta em que esta o prompt.

+
npm install -g yo
+npm install -g generator-firefoxos-app
+
+ +

Com ambos os pacotes acima instalados, vamos dar início a criação da app. No seu diretório de projetos ou onde desejar criar a app chama o generator instalado.

+
yo firefoxos-app
+
+ +

Uma vez chamado esse generator, o mesmo irá fazer alguns questionamentos, o primeiro é claro será o nome da sua aplicação, seguido da descrição e o nome do desenvolvedor.

+

Após a execução do generator, você já terá uma estrutura para desenvolvimento pronta, inclusive com um html inicial, com todas as dependências já instaladas. Vale ressaltar agora algumas tarefas disponíveis no Gruntfile.

+
    +
  • Default: Irá gerar o pacote de distribuição
  • +
  • Test: Até a presente versão do generator (0.1.3) este processo irá simplesmente rodar o validador jsHint
  • +
  • Server: Irá disponibilizar na porta 9001 um simples servidor para testar a sua app
  • +
+

Vamos testar a nossa app. Para tal, rode o comando grunt server e acesse no seu navegador localhost:9001 e devemos ver a seguinte app. Caso nenhuma página seja exibida, revise os passos ateriores e verifique se nenhum erro ocorreu.

+

App inicial

+

Vale ressaltar que a sua app toda estará dentro de uma pasta também chamada app. Nela você encontrará os seus arquivos .html, .js, .css e demais. Antes de começarmos a codificar a nossa app, vamos ver como se instala a mesma.

+

Instalando a app

+

Para fins de teste, não é necessário rodar o comando grunt, sendo que ele irá testar o JS e compactar tudo em um arquivo .zip, basta apontar a instalação para a pasta app dentro do seu projeto. "Mas como eu faço isto?".

+

Indo novamente na App Manager, clicando na lateral esquerda, onde indica "Aplicativos", teremos então disponível no inferior da tela duas opções, vamos nos ater a utilizar a primeira (Adicionar aplicativo hospedado).

+

Clicando nesta opção vamos navegar até a pasta da app e clicar selecionada. Pronto.

+

Simples de se instalar, não acha? O Resultado final deve ser semelhante ao abaixo.

+

App inicial

+

Acessando uma API

+

Quando vamos programar algo mais complexo, geralmente vamos utilizar algo como, câmera, rede, lista de contatos, armazenamento e outras possibilidades. Para utilizarmos essas APIs, precisamos - assim como no desenvolvimento para android - especificar para o usuário no momento de instalação. Estes dados de acesso ficam no arquivo manifes.webapp, se você ainda não deu uma olhada neste arquivo, é nele que fica armazenado dados da app, como nome, descrição, versão, localização de ícones e é claro as permissões que a mesma requer.

+

As permissões ficam na propriedade permissions, na forma de "chave" : True. Algumas das apis são:

+
    +
  • câmera
  • +
  • contacts
  • +
  • desktop-notification
  • +
  • storage
  • +
+

Cada permissão vai mudar o tipo de app que você esta desenvolvendo, mas aí eu sugiro ler mais na MDN aqui. Esse é o básico para iniciar no desenvolvimento de app para FirefoxOS. Na parte dois, vou começar a passar um pouco de código.

+
+ + +
+
+

Translations:

+
    +
+
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/drafts/desenvolvendo-app-firefoxos-pt.html.gz b/en/drafts/desenvolvendo-app-firefoxos-pt.html.gz new file mode 100644 index 000000000..e4c774af2 Binary files /dev/null and b/en/drafts/desenvolvendo-app-firefoxos-pt.html.gz differ diff --git a/en/drafts/editando-o-admin-do-django-pt.html b/en/drafts/editando-o-admin-do-django-pt.html new file mode 100644 index 000000000..921aa1bc4 --- /dev/null +++ b/en/drafts/editando-o-admin-do-django-pt.html @@ -0,0 +1,531 @@ + + + + + + + + Editando o Admin do Django - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Editando o Admin do Django

+
+ +
+
+ +
+

Este artigo foi re-postado no grupo PythonClub. Vamos falar um pouco sobre como customizar o admin do Django. Primeiramente porque? A resposta é bem simples, quero mostrar algo para o usuário sem que ele precise entrar nas apps e fazer alguma consulta para então tomar alguma ação. Alguns exêmplos para isto seriam:

+
+
    +
  • Exibir as vendas do mês em forma de gráfico por região do país
  • +
  • Exibir os últimos comentários adicionados
  • +
  • Exibir log dos ultimos usuários cadastrados
  • +
+
+

O que faremos aqui será exibir os últimos comentários ainda não liberados de um sistema de blog. Vale lembrar que aqui não discutiremos sobre os primeiros passos da aplicação. Para seguirmos adiante, vamos assumir que já temos um projeto básico com uma estrutura simples, abaixo a estrutura inicial do nosso projeto.

+
../blog/
+├── core
+│   ├── __init__.py
+│   ├── admin.py
+│   ├── models.py
+│   ├── tests.py
+│   └── views.py
+├── blog
+│   ├── __init__.py
+│   ├── settings.py
+│   ├── urls.py
+│   └── wsgi.py
+└── manage.py
+
+

Para iniciarmos, precisamos da nossa tabela de comentários, vamos usar a mais simples e básica o possível.

+ ++++ + + + + + + + + + + + + + + + + + + + +
CampoTipo
nomeVarchar(30)
textoText
liberadoBoolean
dataDate
+

Vamos seguir adiante e alterar a página inicial do admin para listar os últimos comentários de um simples sistema de blog. Para comerçar a editar o admin, precisamos inicialmente copiar o template que desejamos para a pasta uma pasta admin dentro ta pasta de templates do nosso projeto. Isto porque o Admin, não passa de uma app como outra qualquer, portanto o sistema de herança vai funcionar aqui, carregamento prioritariamente o seu template. Você pode conseguir o template que desejar (no nosso caso o index.html) dentro do projeto do Django mesmo, no meu caso "C:\Django-1.6.3\django\contrib\admin\templates\admin".

+
../blog/
+├── templates
+│   ├── admin
+│   │   └── index.html
+├── core
+
+

Tire um tempo e brinque um pouco com este template e veja o que acontece se você alterar algumas coisa. Para adicionarmos a nossa listagem, vamos adicionar um painel lateral, para tal vamos adicionar o código abaixo antes do fechamento da ultima tag div. Nele podemos ver uma chamada para uma template_tag, portanto precisamos carrega-la no topo do template.

+
{% load comentarios_tag %}
+...
+...
+...
+<div class="module" id="ultimos-comentarios">
+    <h2>Ultimos Comentários</h2>
+    <h3>Liberar</h3>
+            {% comentarios_n_liberados %}
+</div>
+
+

Esta template trata-se da responsável por fazer a consulta na base de dados e renderizar a nossa lista, portanto ela é uma 'inclusion tag'. Se você não esta familiarizado com 'template tags', talvez queira dar uma olhada na documentação do django.

+

Vamos então criar nossa template tag 'comentarios_n_liberados'. Primeiro devemos criar uma pasta chamada templatetags, dentro da nossa app core. Dentro ta pasta vamos inicializar um pacote python e criar o arquivo comentarios_tag.py. Nele precisamos declarar nosso metodo que deve se chamar 'comentarios_n_liberados' e nele fazer uma simples consulta ao banco buscando os comentários não liberados e por fim registrar a tag apontando para o template que será renderizado. Abaixo o código mais explicado.

+
+
Recomendações
+ Livro Pense em Python na Amazon + Livro Curso Intensivo de Python na Amazon +
from django import template
+from core import models
+
+#Carrega o registro de template tags
+register = template.Library()
+
+#Registra o metodo a seguir como uma inclusion_tag indicando o template a ser renderizad
+@register.inclusion_tag('comentarios_n_liberados.html')
+def comentarios_n_liberados():
+    comentarios = models.comentario.objects.filter(liberado=False).order_by('data')[0:5]
+    return { 'comentarios' : comentarios }
+
+

Abaixo o html do nosso template a ser renderizado, este deve estar dentro da pasta templates da nossa app core.

+
{% if not comentarios %}
+    <p>Nenhum comentário novo</p>
+{% else %}
+    <ul>
+            {% for c in comentarios %}
+            <li class="addlink">
+                    <a href="{{ c.id }}">{{ c.texto|truncatechars:30 }}</a>
+            </li>
+            {% endfor %}
+    </ul>
+{% endif %}
+
+

Com tudo isto feito, basta subir o seu servidor e ver o resultado final, que pode ser visto na imagem abaixo.

+Resultado final +

Lembrando que aqui apenas mostrei como modificar o index do admin, para apenas listar dados do banco, mas você pode ir muito mais além. Abaixo fica a estrutura de diretórios final e um link para download do projeto funcionando.

+
../blog/
+├── core
+│   ├── templates
+│   │   └── comentarios_n_liberados.html
+│   ├── templatetag
+│   │   └── comentarios_tag.py
+│   ├── __init__.py
+│   ├── admin.py
+│   ├── models.py
+│   ├── tests.py
+│   └── views.py
+├── blog
+│   ├── __init__.py
+│   ├── settings.py
+│   ├── urls.py
+│   └── wsgi.py
+├── templates
+│   ├── admin
+│   │   └── index.html
+└── manage.py
+
+

Espero que tenham gostado, criticas/sugestões são bem-vindas. Fontes do Projeto

+

+
+ + +
+
+

Translations:

+
    +
+
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/drafts/editando-o-admin-do-django-pt.html.gz b/en/drafts/editando-o-admin-do-django-pt.html.gz new file mode 100644 index 000000000..121b3ab18 Binary files /dev/null and b/en/drafts/editando-o-admin-do-django-pt.html.gz differ diff --git a/en/drafts/menu-dinamico-com-apps-do-django-pt.html b/en/drafts/menu-dinamico-com-apps-do-django-pt.html new file mode 100644 index 000000000..fd2f8ba3a --- /dev/null +++ b/en/drafts/menu-dinamico-com-apps-do-django-pt.html @@ -0,0 +1,519 @@ + + + + + + + + Menu dinâmico com as apps do django - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Menu dinâmico com as apps do django

+
+ +
+
+ +
+

Digamos que sua empresa trabalha com Django desenvolvendo aplicações cujas apps são plugaveis e reutilizáveis. Por que não se aproveitar de um certo padrão de desenvolvimento para desenvolver menus que se modificam de acordo com as apps que estão no projeto? Como o objetivo aqui não é desenvolver uma app em si, vamos utilizar um projeto com algumas de modelo. Se desejar estudar mais sobre desenvolvimento Django, a documentação é muito boa, mas também temos blogs e sites excelentes sobre o assunto.

+

Para conseguirmos atingir esse objetivo, vamos utilizar a api Django.apps que está disponível a partir da versão 1.7. +Com esta api, vamos percorrer as apps e se possível, criar um link para uma URL base de cada uma delas. Para começo, baixe os fontes do projeto aqui, rode o pip install do projeto e no fim, sua estrutura de pastas deve ficar como abaixo.

+
../menusapp/
+├── comentarios
+│   ├── templates
+│   │   └── comentarios
+│   │      └── listagem.html
+│   ├── __init__.py
+│   ├── admin.py
+│   ├── apps.py
+│   ├── models.py
+│   ├── tests.py
+│   ├── urls.py
+│   └── views.py
+├── core
+│   ├── templates
+│   │   └── core
+│   │       └── base.html
+│   │       └── listagem.html
+│   ├── __init__.py
+│   ├── admin.py
+│   ├── apps.py
+│   ├── models.py
+│   ├── tests.py
+│   ├── urls.py
+│   └── views.py
+├── menusapp
+│   ├── __init__.py
+│   ├── settings.py
+│   ├── urls.py
+│   └── wsgi.py
+└── manage.py
+
+

Rode o projeto e veja como é o seu funcionamento. É na app core que temos a base do nosso HTML, então será nele que iremos trabalhar. Quando se trata de algo que será renderizado no template base, eu gosto muito de utilizar 'template tags' para facilitar. +Neste link tem mais um exemplo de utilização de 'template tag' caso esteja interessado.

+

Vamos então criar uma pasta chamada template_tag e dentro dela a nossa tag. Vamos chamá-la de menus_tag.py. Abaixo vamos ver um pouco da nossa tag. +O código é bem simples e auto explicativo, importamos as bibliotecas necessárias e realizamos o @register da tag com o nome do template que será renderizado. +E por ultimo, retornamos uma tupla de dados para o template.

+
+
Recomendações
+ + +
from django import template
+from django.apps import apps
+
+#Carrega o registro de template tags
+register = template.Library()
+
+#Registra o metodo a seguir como uma inclusion_tag indicando o template a ser renderizado
+@register.inclusion_tag('menus_por_app.html')
+def menus_por_app():
+    lst = apps.get_app_configs()
+    return { 'lst_apps' : lst }
+
+

O template está abaixo e é simplesmente um for percorrendo as apps e gerando uma lista com os seus menus. As outras propriedades você pode ver direto na documentação. +Algumas ressalvas para o que foi feito por questões de praticidade para uso posterior, utilizei um with para concatenar e gerar a url e criei um apelido para a url para validar a existência da mesma. Fora isto, nada de novo.

+
{% if not lst_apps %}
+                    <p>Nenhuma app</p>
+            {% else %}
+                    <ul>
+                            {% for app in lst_apps %}
+                                    {% with app.name|add:":listagem" as link %}
+                                            {% url link as the_url %}
+                                                    {% if the_url %}
+                                                    <li>
+                                                            <a href="{% url link %}">{{ app.verbose_name|truncatechars:30 }}</a>
+                                                    </li>
+                                                    {% endif %}
+                                    {% endwith %}
+                            {% endfor %}
+                    </ul>
+            {% endif %}
+
+Resultado final +

No final, o resultado obtido deve ser semelhante ao acima. Repare que está listando as duas aplicações. E acima de tudo, repare que só serão exibidos os links cuja app tenha um namespace de mesmo nome e uma url de nome listagem. +A estrutura final pode ser vista abaixo. Atente-se aos nomes tanto das pastas quanto dos arquivos, pois qualquer diferença pode causar o não funcionamento.

+
../menusapp/
+├── comentarios
+│   ├── templates
+│   │   └── comentarios
+│   │      └── listagem.html
+│   ├── __init__.py
+│   ├── admin.py
+│   ├── apps.py
+│   ├── models.py
+│   ├── tests.py
+│   ├── urls.py
+│   └── views.py
+├── core
+│   ├── templates
+│   │   └── core
+│   │   │   └── base.html
+│   │   │   └── listagem.html
+│   │   └── menus_por_app.html
+│   ├── templatetags
+│   │   ├── __init__.py
+│   │   └── menus_tag.py
+│   ├── __init__.py
+│   ├── admin.py
+│   ├── apps.py
+│   ├── models.py
+│   ├── tests.py
+│   ├── urls.py
+│   └── views.py
+├── menusapp
+│   ├── __init__.py
+│   ├── settings.py
+│   ├── urls.py
+│   └── wsgi.py
+└── manage.py
+
+

Espero que tenham gostado, críticas e sugestões são bem-vindas. Fontes do Projeto

+

+
+ + +
+
+

Translations:

+
    +
+
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/drafts/menu-dinamico-com-apps-do-django-pt.html.gz b/en/drafts/menu-dinamico-com-apps-do-django-pt.html.gz new file mode 100644 index 000000000..443cdc569 Binary files /dev/null and b/en/drafts/menu-dinamico-com-apps-do-django-pt.html.gz differ diff --git a/en/drafts/my-azure-data-fundamentals-certification.html b/en/drafts/my-azure-data-fundamentals-certification.html new file mode 100644 index 000000000..8f1c2cff3 --- /dev/null +++ b/en/drafts/my-azure-data-fundamentals-certification.html @@ -0,0 +1,538 @@ + + + + + + + + My Experience with Azure Data Fundamentals certification - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+ + +
+

+
+ + +
+
+

Translations:

+ +
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/drafts/my-azure-data-fundamentals-certification.html.gz b/en/drafts/my-azure-data-fundamentals-certification.html.gz new file mode 100644 index 000000000..f42c5b6d5 Binary files /dev/null and b/en/drafts/my-azure-data-fundamentals-certification.html.gz differ diff --git a/en/drafts/pages/businesscard.html b/en/drafts/pages/businesscard.html new file mode 100644 index 000000000..80205db43 --- /dev/null +++ b/en/drafts/pages/businesscard.html @@ -0,0 +1,304 @@ + + + + + + + + businesscard - Sipmann + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+

businesscard

+ +
+

Todo

+
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/drafts/pages/businesscard.html.gz b/en/drafts/pages/businesscard.html.gz new file mode 100644 index 000000000..07a9a502a Binary files /dev/null and b/en/drafts/pages/businesscard.html.gz differ diff --git a/en/drafts/pages/services.html b/en/drafts/pages/services.html new file mode 100644 index 000000000..570240cea --- /dev/null +++ b/en/drafts/pages/services.html @@ -0,0 +1,304 @@ + + + + + + + + Services - Sipmann + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+

Services

+ +
+

Testing

+
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/drafts/pages/services.html.gz b/en/drafts/pages/services.html.gz new file mode 100644 index 000000000..4fd27d89a Binary files /dev/null and b/en/drafts/pages/services.html.gz differ diff --git a/en/drafts/pages/servicos-pt.html b/en/drafts/pages/servicos-pt.html new file mode 100644 index 000000000..eb8f343a2 --- /dev/null +++ b/en/drafts/pages/servicos-pt.html @@ -0,0 +1,304 @@ + + + + + + + + Serviços - Sipmann + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+

Serviços

+ +
+

Testes

+
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/drafts/pages/servicos-pt.html.gz b/en/drafts/pages/servicos-pt.html.gz new file mode 100644 index 000000000..3b1e1caf0 Binary files /dev/null and b/en/drafts/pages/servicos-pt.html.gz differ diff --git a/en/drafts/schedule-blog-post-with-powershell-and-pelican.html b/en/drafts/schedule-blog-post-with-powershell-and-pelican.html new file mode 100644 index 000000000..bbaafb931 --- /dev/null +++ b/en/drafts/schedule-blog-post-with-powershell-and-pelican.html @@ -0,0 +1,545 @@ + + + + + + + + Scheduling blog posts with Powershell and Pelican - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Scheduling blog posts with Powershell and Pelican

+
+ +
+
+ +
+

Hy folks, first time posting here on dev.to :). Recently I've been migrating some of my scripts from bash to PowerShell and I thought that would be a good time to code an automation script to publish posts on my personal blog. I host my blog with Github Pages and I use Pelican as a static site generator. The main problem I have with this toolkit, is the lack of scheduling posts. For those who are new to Pelican, the post system is similar to dev.to, we write the posts using Markdown and we have a Status tag to tell when the post is a draft or not.

+

The main idea of my script is, run through the Markdown files an check those who have Draft as status. Once I found any post, I start getting some info like the Date and the Slug. The Date part is a little tricky because we need to find the line, split the text and then parse it to do date comparisons. If the post date is lower then the current timespan I replace the Status: Draft tag and save the file. After that all we have to do is commit to git and let it go.

+
$postsPath = "E:\projetos\sipmann.github.io\content\";
+$files = Get-ChildItem $postsPath -File -Filter *.md
+
+<# Get the current datetime so we can compare with the psot date #>
+$now = Get-Date
+
+<# Set the current location, with this we can work with the git commands #>
+Set-Location $postsPath
+
+foreach($file in $files) {
+
+    <# Get's only posts with draft status #>
+    $isDraft = Get-Content ($postsPath + $file) | Where-Object { $_ -ccontains "Status: Draft" }
+
+    if ($isDraft) {
+
+        <# First we find the line with the date, then we get only the datetime and then parse it #>
+        $pubDate = [datetime]::parseexact(((Get-Content ($postsPath + $file) | Where-Object { $_ -Match "^Date:*" }) -split '\s+', 2)[1], 'yyyy-MM-dd HH:mm', $null)
+
+        <# TODO: Maybe call google and bing api to submit a new url #>
+        $slug = ((Get-Content ($postsPath + $file) | Where-Object { $_ -Match "^Slug:*" }) -split '\s+', 2)[1]
+
+        if ($now -ge $pubDate) {
+
+            <# Sets the content without the Draft status #>
+            ((Get-Content ($postsPath + $file)) -replace 'Status: Draft', '') | Set-Content ($postsPath + $file)
+
+            git add .
+            git commit -m ("New scheduled post: " + $file)
+            git push origin master
+        }
+    }
+}
+
+ +

Hope you find the script useful, and if you are interested in the other scripts I'm making with PowerShell, take a look at my github repo, still lacks many of my scripts, but it's there where I'll keep them updated. See ya.

+
+ + +
+
+

Translations:

+
    +
+
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/drafts/schedule-blog-post-with-powershell-and-pelican.html.gz b/en/drafts/schedule-blog-post-with-powershell-and-pelican.html.gz new file mode 100644 index 000000000..95002ded7 Binary files /dev/null and b/en/drafts/schedule-blog-post-with-powershell-and-pelican.html.gz differ diff --git a/en/drafts/script-de-inicializacao-raspberry-pt.html b/en/drafts/script-de-inicializacao-raspberry-pt.html new file mode 100644 index 000000000..d99aad6dc --- /dev/null +++ b/en/drafts/script-de-inicializacao-raspberry-pt.html @@ -0,0 +1,572 @@ + + + + + + + + Scripts de inicialização no raspberry pi - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Scripts de inicialização no raspberry pi

+
+ +
+
+ +
+

Instalei essa semana o gitea no meu raspberry pi B + e queria iniciar ele no boot... Não sou profundo conhecedor de linux, então, logo não sabia como fazer isto da melhor forma. +As versões atuais do Raspbian utilizam o systemd para gerenciar os serviços e confesso que nunca havia utilizado o systemctl para nada.

+

Vamos começa criando um arquivo de serviço dentro da pasta /etc/systemd/system, vale ressaltar que a pasta system deve (em teoria) ser reservada para pacotes do sistema. +Vamos criar o arquivo com o nome gitea.service dentro da pasta antes mencionada. Abaixo podemos ver como ficou o arquivo e um detalhamento após ele.

+
[Unit]
+Description=Gitea Service
+After=network.target
+
+[Service]
+Type=simple
+User=root
+WorkingDirectory=/root/
+ExecStart=/root/gitea web
+Restart=on-abort
+
+

A composição do arquivo é bem simples, mas vamos a alguns detalhes. Type possui várias opções (simple, forking, oneshot), utilizamos simple uma vez que o nosso processo executara, permanecerá rodando e não executa um fork de processo. +Fork como acabo de comentar, deve ser utilizado caso o processo que for executando disparar mais processos. User irá definir o usuário do processo. WorkingDirectory definira onde o processo terá a sua base de execução, como o gitea esta localizada na pasta root, +aponto para lá. O ExecStart é bem simples e direto, deve chamar a execução do processo passando parametros caso seja necessário. O Restart é o que nos garantirá que o serviço permanecerá rodando caso haja algum imprevisto (exceto o fato de um usuário chamar o stop).

+

Salve o arquivo e vamos rodar um refresh para o SO perceber o novo serviço. Assim rodamos systemctl daemon-reload. Sempre que alterarmos um serviço ou criarmos um novo, este comando deve ser executado, caso contrário o próprio systemctl pode lhe alertar da necessidade. +Após reacarregar os serviços, vamos habilitar o serviço que criamos rodando systemctl enable gitea, feito isto temos alguns comandos uteis.

+
    +
  • systemctl start gitea
  • +
  • systemctl stop gitea
  • +
  • systemctl status gitea
  • +
+

O comando de status pode ser visto como exemplo abaixo.

+
● gitea.service - Gitea Service
+  Loaded: loaded (/etc/systemd/system/gitea.service; enabled; vendor preset: enabled)
+  Active: active (running) since Wed 2017-10-04 00:37:34 UTC; 52min ago
+Main PID: 1087 (gitea)
+  CGroup: /system.slice/gitea.service
+          └─1087 /root/gitea web
+
+Oct 04 00:38:31 gitserver gitea[1087]: [Macaron] 2017-10-04 00:38:31: Completed /explore/users 200 OK in 80.106173ms
+Oct 04 00:38:31 gitserver gitea[1087]: [Macaron] 2017-10-04 00:38:31: Started GET /img/favicon.png for 192.168.1.4
+Oct 04 00:38:31 gitserver gitea[1087]: [Macaron] [Static] Serving /img/favicon.png
+
+

Após estes processos, você pode reiniciar seu raspberry que o gitea irá subir e funcionar. Ressalto que, preste atenção tanto no WorkingDirectory quanto no ExecStart, no caso do gitea, ele utiliza o workingdir e a forma de start para saber onde irá largar os arquivos por padrão, então ou você configura ele com caminhos absolutos ou cuidar na forma de start (ao menos é o que consegui pegar até agora).

+

+
+ + +
+
+

Translations:

+
    +
+
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/drafts/script-de-inicializacao-raspberry-pt.html.gz b/en/drafts/script-de-inicializacao-raspberry-pt.html.gz new file mode 100644 index 000000000..c0b6947db Binary files /dev/null and b/en/drafts/script-de-inicializacao-raspberry-pt.html.gz differ diff --git a/en/feeds/all-en.atom.xml b/en/feeds/all-en.atom.xml new file mode 100644 index 000000000..13ff94dac --- /dev/null +++ b/en/feeds/all-en.atom.xml @@ -0,0 +1,813 @@ + +Sipmannhttps://www.sipmann.com/en/2020-12-21T13:30:00-03:00Monitoring MySQL restarts with PowerShell2020-12-21T13:30:00-03:002020-12-21T13:30:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-12-21:/en/monitoring-mysql-restarts-with-powershell.html<p>Hey folks, it's time for another PowerShell script. If you haven't seen the other ones, check the links below.</p> +<ul> +<li><a href="https://www.sipmann.com/en/monitoring-mysql-replication-with-powershell.html">Monitoring MySQL replication with PowerShell</a></li> +</ul> +<p>Well, this one it's a pretty simple script, but again, if your customer doesn't have a Zabbix server or doesn't allow you to setup one to …</p><p>Hey folks, it's time for another PowerShell script. If you haven't seen the other ones, check the links below.</p> +<ul> +<li><a href="https://www.sipmann.com/en/monitoring-mysql-replication-with-powershell.html">Monitoring MySQL replication with PowerShell</a></li> +</ul> +<p>Well, this one it's a pretty simple script, but again, if your customer doesn't have a Zabbix server or doesn't allow you to setup one to do the monitoring, a set of scripts can be handy. We start executing some basic query <code>SHOW GLOBAL STATUS LIKE 'Uptime'</code>, with that we'll get exactly what we're looking for.</p> +<p>If for some reason, the command fails (watch for the "global" variable called <code>$lastExitCode</code>), we send an e-mail telling you about that connection problem.</p> +<p>And then, we get to the part where we parse the value, this one is pretty similar to the parse we did on the first post about using PowerShell to monitor MySQL. But we basically look for the Value line, split it by space and then parse the second position to an integer. And then all we have to do is check if the uptime is lower than our threshold, if it is we send an e-mail.</p> +<div class="highlight"><pre><span></span><code><span class="nv">$MailFrom</span> <span class="p">=</span> <span class="s1">&#39;maurio[at]sipmann.com&#39;</span> +<span class="nv">$MailTo</span> <span class="p">=</span> <span class="s1">&#39;mauricio[at]sipmann.com&#39;</span> +<span class="nv">$MysqlHost</span> <span class="p">=</span> <span class="s1">&#39;127.0.0.1&#39;</span> +<span class="nv">$MysqlUser</span> <span class="p">=</span> <span class="s1">&#39;root&#39;</span> +<span class="nv">$MysqlPass</span> <span class="p">=</span> <span class="s1">&#39;123&#39;</span> + + +<span class="nv">$data</span> <span class="p">=</span> <span class="p">$(</span><span class="n">mysql</span> <span class="n">-h</span> <span class="nv">$MysqlHost</span> <span class="n">-u</span> <span class="nv">$MysqlUser</span> <span class="n">-p</span><span class="s2">&quot;$MysqlPass&quot;</span> <span class="n">-e</span> <span class="s2">&quot;SHOW GLOBAL STATUS LIKE &#39;Uptime&#39; \G&quot;</span><span class="p">)</span> + +<span class="cm">&lt;# Unable to execute the sql Command #&gt;</span> +<span class="k">if</span> <span class="p">(</span><span class="nv">$lastExitCode</span> <span class="o">-eq</span> <span class="n">1</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Send-MailMessage</span> <span class="n">-To</span> <span class="nv">$MailTo</span> <span class="n">-From</span> <span class="nv">$MailFrom</span> <span class="n">-Subject</span> <span class="s1">&#39;Connection problem&#39;</span> <span class="n">-bodyAsHtml</span> <span class="s2">&quot;Connection problem on host ${MysqlHost}&quot;</span> <span class="n">-Credential</span> <span class="nb">Get-Credential</span> <span class="n">-SmtpServer</span> <span class="s1">&#39;smtp.office365.com&#39;</span> <span class="n">-Port</span> <span class="n">587</span> <span class="n">-UseSsl</span> + <span class="n">exit</span> +<span class="p">}</span> + +<span class="nv">$UpTime</span> <span class="p">=</span> <span class="no">[int]</span><span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Value:&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> + +<span class="cm">&lt;# If the uptime is lower then 20 minutes #&gt;</span> +<span class="k">if</span> <span class="p">(</span><span class="nv">$UpTime</span> <span class="o">-lt</span> <span class="n">1200</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Send-MailMessage</span> <span class="n">-To</span> <span class="nv">$MailTo</span> <span class="n">-From</span> <span class="nv">$MailFrom</span> <span class="n">-Subject</span> <span class="s2">&quot;MySQL Restarted&quot;</span> <span class="n">-bodyAsHtml</span> <span class="s2">&quot;MySQL host ${MysqlHost} restarted less than 20 minutes ago&quot;</span> <span class="n">-Credential</span> <span class="nb">Get-Credential</span> <span class="n">-SmtpServer</span> <span class="s1">&#39;smtp.office365.com&#39;</span> <span class="n">-Port</span> <span class="n">587</span> <span class="n">-UseSsl</span> +<span class="p">}</span> +</code></pre></div> + +<p>This script (and the other ones I use) is available at my GitHub <a href="https://github.com/sipmann/PowerShellScripts">here</a>. Keep in mind that the ones on the GitHub repo, are a little different from here.</p>Changing a MySQL user password across multiple application instances without downtime2020-12-09T13:40:00-03:002020-12-09T13:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-12-09:/en/mysql-dual-password-functionality.html<p>Do you need to change the password of a MySQL user that it's being used in an application, and can't allow a single downtime? Well, MySQL 8.0.14 came with a feature called <a href="https://dev.mysql.com/doc/refman/8.0/en/password-management.html#dual-passwords">Dual Password Support</a>, with it you can change the password keeping the previous password as a …</p><p>Do you need to change the password of a MySQL user that it's being used in an application, and can't allow a single downtime? Well, MySQL 8.0.14 came with a feature called <a href="https://dev.mysql.com/doc/refman/8.0/en/password-management.html#dual-passwords">Dual Password Support</a>, with it you can change the password keeping the previous password as a kind of backup. That way you still can log in using the old password or can start using the new one. With that, the password change workflow it's the following.</p> +<p>1) Change password keeping the old one;</p> +<p>2) Deploy the new config to your app/cluster;</p> +<p>3) Discard the old password.</p> +<p>To change the password and keep the old one, you have the following command.</p> +<div class="highlight"><pre><span></span><code><span class="k">ALTER</span> <span class="n">USER</span> <span class="s1">&#39;appuser&#39;</span><span class="o">@</span><span class="s1">&#39;localhost&#39;</span> <span class="n">IDENTIFIED</span> <span class="k">BY</span> <span class="s1">&#39;new_password&#39;</span> <span class="n">RETAIN</span> <span class="n">CURRENT</span> <span class="n">PASSWORD</span><span class="p">;</span> +</code></pre></div> + +<p>To discard the old one, run the following.</p> +<div class="highlight"><pre><span></span><code><span class="k">ALTER</span> <span class="n">USER</span> <span class="s1">&#39;appuser&#39;</span><span class="o">@</span><span class="s1">&#39;localhost&#39;</span> <span class="n">DISCARD</span> <span class="n">OLD</span> <span class="n">PASSWORD</span><span class="p">;</span> +</code></pre></div> + +<p>And you are done. Hope you find it as useful as I :)</p>Apache Nifi JSON to SQL Replacing underscore2020-12-02T14:00:00-03:002020-12-02T14:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-12-02:/en/apache-nifi-json-to-sql-replacing-underscore.html<p>Recently I was doing some ETL with Apache NiFi. But after a few minutes of drawing my flow, I saw that the component ConvertJSONToSQL was replacing the underscore ('_') from the field name in the where condition (I was preparing an Update SQL). That was weird because, at the set …</p><p>Recently I was doing some ETL with Apache NiFi. But after a few minutes of drawing my flow, I saw that the component ConvertJSONToSQL was replacing the underscore ('_') from the field name in the where condition (I was preparing an Update SQL). That was weird because, at the set statement, the field name was kept intact. After some research, I found that the property (see bellow) <code>Translate Field Names</code> was responsible for that weird replacement.</p> +<p><img alt="Apache NiFi JSONToSQL config" src="/images/apache_nifi_jsontosql.png"></p> +<p>Before setting it to <strong>FALSE</strong>, be aware that the properties on your JSON data must match exactly the name of your fields.</p>Blocking a user on SQL Server based on a schedule2020-11-14T07:00:00-03:002020-11-14T07:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-11-14:/en/blocking-user-on-sql-server-based-on-schedule.html<p>Ok, some time ago, I've posted about how you can set limits to connections on SQL Server using the <a href="https://www.sipmann.com/limiting-connection-resources-sql-server.html#.X6Cz8IhKhPY">Resource Governor</a>. But what if you can't use it? You always can block logins using a login trigger, but I don't like the idea of having selects running on every login …</p><p>Ok, some time ago, I've posted about how you can set limits to connections on SQL Server using the <a href="https://www.sipmann.com/limiting-connection-resources-sql-server.html#.X6Cz8IhKhPY">Resource Governor</a>. But what if you can't use it? You always can block logins using a login trigger, but I don't like the idea of having selects running on every login. So I came across with a solution using a stored procedure, a table and the Agent.</p> +<p>The main idea is, store the time that a user must be blocked and using the Agent, disable or enable the user. Bellow you can see the table (the table is in Portuguese, but I have a few comment blocks to help you).</p> +<div class="highlight"><pre><span></span><code><span class="k">CREATE</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"> </span><span class="p">(</span><span class="w"></span> +<span class="w"> </span><span class="n">Id</span><span class="w"> </span><span class="nc">INT</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">LoginName</span><span class="w"> </span><span class="nc">NVARCHAR</span><span class="p">(</span><span class="mi">100</span><span class="p">)</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">HrInicio</span><span class="w"> </span><span class="nc">TIME</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"> </span><span class="cm">/* Startint block time */</span><span class="w"></span> +<span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="nc">TIME</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"> </span><span class="cm">/* Ending block time */</span><span class="w"></span> +<span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="nc">INT</span><span class="w"> </span><span class="k">DEFAULT</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="cm">/* 0 = unblocked, 1 = blocked */</span><span class="w"></span> +<span class="w"> </span><span class="k">PRIMARY</span><span class="w"> </span><span class="k">KEY</span><span class="w"> </span><span class="p">(</span><span class="n">Id</span><span class="p">)</span><span class="w"></span> +<span class="p">);</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> + +<span class="cm">/* Don&#39;t block the SA user, precautions, you know */</span><span class="w"></span> +<span class="k">ALTER</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"></span> +<span class="w"> </span><span class="k">ADD</span><span class="w"> </span><span class="k">CONSTRAINT</span><span class="w"> </span><span class="n">chk_users</span><span class="w"> </span><span class="k">CHECK</span><span class="w"> </span><span class="p">(</span><span class="n">LoginName</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;sa&#39;</span><span class="p">));</span><span class="w"></span> + +<span class="k">ALTER</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"></span> +<span class="w"> </span><span class="k">ADD</span><span class="w"> </span><span class="k">CONSTRAINT</span><span class="w"> </span><span class="n">chk_hora_final_maior</span><span class="w"> </span><span class="k">CHECK</span><span class="w"> </span><span class="p">(</span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="n">HrInicio</span><span class="p">);</span><span class="w"></span> + +<span class="k">ALTER</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"></span> +<span class="w"> </span><span class="k">ADD</span><span class="w"> </span><span class="k">CONSTRAINT</span><span class="w"> </span><span class="n">chk_status_bloqueio</span><span class="w"> </span><span class="k">CHECK</span><span class="w"> </span><span class="p">(</span><span class="n">Bloqueado</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">));</span><span class="w"></span> + +<span class="k">CREATE</span><span class="w"> </span><span class="k">SEQUENCE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">seq_HorariosBloqueio</span><span class="w"> </span><span class="k">START</span><span class="w"> </span><span class="k">WITH</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="n">INCREMENT</span><span class="w"> </span><span class="k">BY</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +</code></pre></div> + +<p>After creating the table, let's check the procedure that will handle the enabling/disabling the users. Be aware that on the procedure, I've set the database name where the table was stored, you can change it replacing the <code>DBATOOLS</code> text to the database name where you created the table.</p> +<div class="highlight"><pre><span></span><code><span class="k">IF</span><span class="w"> </span><span class="nf">OBJECT_ID</span><span class="p">(</span><span class="s1">&#39;dbo.sp_ValidarLogin&#39;</span><span class="p">)</span><span class="w"> </span><span class="k">IS</span><span class="w"> </span><span class="k">NULL</span><span class="w"></span> +<span class="w"> </span><span class="k">EXEC</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;CREATE PROCEDURE dbo.sp_ValidarLogin AS RETURN 0;&#39;</span><span class="p">);</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> + +<span class="k">CREATE</span><span class="w"> </span><span class="ow">OR</span><span class="w"> </span><span class="k">ALTER</span><span class="w"> </span><span class="k">PROC</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">sp_ValidarLogin</span><span class="w"></span> +<span class="k">AS</span><span class="w"> </span><span class="k">BEGIN</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="nc">NVARCHAR</span><span class="p">(</span><span class="mi">100</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="nc">TIME</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="k">SET</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nf">CAST</span><span class="p">(</span><span class="nf">GETDATE</span><span class="p">()</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="nc">TIME</span><span class="p">);</span><span class="w"></span> + +<span class="w"> </span><span class="cm">/* Block the ones that aren&#39;t blocked already and maches the time */</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="n">block_cursor</span><span class="w"> </span><span class="nc">CURSOR</span><span class="w"></span> +<span class="w"> </span><span class="k">FOR</span><span class="w"> </span><span class="k">SELECT</span><span class="w"> </span><span class="n">LoginName</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&lt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&gt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"></span> +<span class="w"> </span><span class="k">OPEN</span><span class="w"> </span><span class="n">block_cursor</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">block_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> + +<span class="w"> </span><span class="k">WHILE</span><span class="w"> </span><span class="nb">@@FETCH_STATUS</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"></span> +<span class="w"> </span><span class="k">BEGIN</span><span class="w"></span> +<span class="w"> </span><span class="k">exec</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;ALTER LOGIN &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="s1">&#39; DISABLE;&#39;</span><span class="p">);</span><span class="w"></span> + +<span class="w"> </span><span class="k">print</span><span class="w"> </span><span class="s1">&#39;Bloqued usuario &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">block_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> +<span class="w"> </span><span class="k">END</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">CLOSE</span><span class="w"> </span><span class="n">block_cursor</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="k">DEALLOCATE</span><span class="w"> </span><span class="n">block_cursor</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">UPDATE</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">SET</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&lt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&gt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"></span> + + +<span class="w"> </span><span class="cm">/* Enable up who was blocked */</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="nc">CURSOR</span><span class="w"></span> +<span class="w"> </span><span class="k">FOR</span><span class="w"> </span><span class="k">SELECT</span><span class="w"> </span><span class="n">LoginName</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="p">(</span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">OR</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="p">)</span><span class="w"></span> +<span class="w"> </span><span class="k">OPEN</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> + +<span class="w"> </span><span class="k">WHILE</span><span class="w"> </span><span class="nb">@@FETCH_STATUS</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"></span> +<span class="w"> </span><span class="k">BEGIN</span><span class="w"></span> +<span class="w"> </span><span class="k">exec</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;ALTER LOGIN &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"> </span><span class="o">+</span><span class="s1">&#39; ENABLE;&#39;</span><span class="p">);</span><span class="w"></span> + +<span class="w"> </span><span class="k">print</span><span class="w"> </span><span class="s1">&#39;Unbloqued usuario &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> +<span class="w"> </span><span class="k">END</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">CLOSE</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="k">DEALLOCATE</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">UPDATE</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">SET</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="p">(</span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">OR</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="p">)</span><span class="w"></span> +<span class="k">END</span><span class="p">;</span><span class="w"></span> +</code></pre></div> + +<p>Ok, so now all you have to do, is schedule a job to run that stored procedure from minute to minute. Again, the main idea is tell the procedure when a user must be blocked and when it'll be unblocked. </p> +<div class="highlight"><pre><span></span><code><span class="err"> -- Will block the user protheus from 10 AM till 15 PM</span> +<span class="err"> INSERT INTO dbo.HorariosBloqueio (Id, LoginName, HrInicio, HrTermino) VALUES (NEXT VALUE FOR seq_HorariosBloqueio, &#39;protheus&#39;, &#39;10:00:00&#39;, &#39;15:00:00&#39;);</span> +</code></pre></div>How to set columns on select using Entity Framework2020-10-28T19:00:00-03:002020-10-28T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-28:/en/select_specific_fields_with_efcore.html<p>So, you use Entity Framework Core, and you usually code your selects like the following, maybe you are getting too much data.</p> +<div class="highlight"><pre><span></span><code><span class="kt">var</span> <span class="n">products</span> <span class="p">=</span> <span class="n">Products</span> + <span class="p">.</span><span class="n">Where</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span> <span class="p">&gt;</span> <span class="m">0</span><span class="p">)</span> + <span class="p">.</span><span class="n">OrderBy</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">)</span> + <span class="p">.</span><span class="n">ToList</span><span class="p">()</span> +</code></pre></div> + +<p>Running the query above, on my table, you'll get the following output, take a look …</p><p>So, you use Entity Framework Core, and you usually code your selects like the following, maybe you are getting too much data.</p> +<div class="highlight"><pre><span></span><code><span class="kt">var</span> <span class="n">products</span> <span class="p">=</span> <span class="n">Products</span> + <span class="p">.</span><span class="n">Where</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span> <span class="p">&gt;</span> <span class="m">0</span><span class="p">)</span> + <span class="p">.</span><span class="n">OrderBy</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">)</span> + <span class="p">.</span><span class="n">ToList</span><span class="p">()</span> +</code></pre></div> + +<p>Running the query above, on my table, you'll get the following output, take a look at how many columns you are getting back from your database.</p> +<p><img alt="Screenshot with every single column" src="/images/ef_core_allcolumns.png"></p> +<p>In my case, I only care about the Title, PublishedData, and a small description. So to get back only these fields, we have a few options. In the first one, we'll set the fields and return them as a dynamic object, the second one, is to give the .NET a class to use. </p> +<div class="highlight"><pre><span></span><code><span class="kt">var</span> <span class="n">products</span> <span class="p">=</span> <span class="n">Products</span> + + <span class="p">.</span><span class="n">Select</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="k">new</span> <span class="p">{</span><span class="n">p</span><span class="p">.</span><span class="n">ProductID</span><span class="p">,</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">,</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span><span class="p">,</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitPrice</span><span class="p">})</span> + <span class="c1">//.Select(p =&gt; new ProductDTO {p.ProductID, p.ProductName, p.UnitsInStock, p.UnitPrice})</span> + + <span class="p">.</span><span class="n">Where</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span> <span class="p">&gt;</span> <span class="m">0</span><span class="p">)</span> + <span class="p">.</span><span class="n">OrderBy</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">)</span> + <span class="p">.</span><span class="n">ToList</span><span class="p">()</span> +</code></pre></div> + +<p><img alt="Screenshot with fewer columns and also fewer data size" src="/images/ef_core_less_columns.png"></p>Zabbix Running on Low Memory Mode2020-10-20T19:00:00-03:002020-10-20T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-20:/en/zabbix-running-on-low-memory-mode.html<p>Hey folks, another Zabbix post today. This one it's about increasing the Zabbix Server Cache. It's pretty common (if you have the default settings only) get a warning about your <code>Zabbix value cache running on low memory mode</code> at your dashboard or logs.</p> +<p><img alt="Zabbix Dashboard warning about the memory problem" src="/images/zabbix_low_memory_mode.png"> +<img alt="Zabbix Dashboard cache graph 70% used" src="/images/zabbix_cache_filling.png"></p> +<p>To solve, go back to your Zabbix …</p><p>Hey folks, another Zabbix post today. This one it's about increasing the Zabbix Server Cache. It's pretty common (if you have the default settings only) get a warning about your <code>Zabbix value cache running on low memory mode</code> at your dashboard or logs.</p> +<p><img alt="Zabbix Dashboard warning about the memory problem" src="/images/zabbix_low_memory_mode.png"> +<img alt="Zabbix Dashboard cache graph 70% used" src="/images/zabbix_cache_filling.png"></p> +<p>To solve, go back to your Zabbix config file (<code>zabbix_server.conf</code>) and look for the tag <em>CacheSize</em>. Uncomment it and set to a value bigger than 8M (8M it's the default value). In my case, we set a cache of 100M. After the change, restart the service.</p> +<div class="highlight"><pre><span></span><code><span class="c1">### Option: CacheSize</span> +<span class="c1"># Size of configuration cache, in bytes.</span> +<span class="c1"># Shared memory size for storing host, item and trigger data.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 128K-64G</span> +<span class="c1"># Default:</span> +<span class="na">CacheSize</span><span class="o">=</span><span class="s">100M #uncomment this line</span> +</code></pre></div> + +<p><img alt="Zabbix Dashboard resolved memory problem" src="/images/zabbix_low_memory_solved.png"></p> +<p>See ya folks.</p>Monitoring MySQL Replication Status with PowerShell2020-10-14T19:00:00-03:002020-10-14T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-14:/en/monitoring-mysql-replication-with-powershell.html<p>I've been migration some bash scripts that I have to PowerShell, and it's time to migrate a script that monitors the replication of a MySQL database. The credit for the original script goes to <a href="https://handyman.dulare.com/mysql-replication-status-alerts-with-bash-script/">Paweł</a>. It's a simple script where I seek a few tags/fields that we get from …</p><p>I've been migration some bash scripts that I have to PowerShell, and it's time to migrate a script that monitors the replication of a MySQL database. The credit for the original script goes to <a href="https://handyman.dulare.com/mysql-replication-status-alerts-with-bash-script/">Paweł</a>. It's a simple script where I seek a few tags/fields that we get from <code>SHOW SLAVE STATUS\G</code> command, the fields are. <code>Slave_IO_Running</code>, <code>Slave_SQL_Running</code>, and <code>Seconds_Behind_Master</code>. I still need to figure out the proper way to store/read variables like usernames and passwords, if you have any tips, feel free to even make a pull request (<a href="https://github.com/sipmann/PowerShellScripts">here</a>) at the git where I'll store some scripts.</p> +<div class="highlight"><pre><span></span><code><span class="cm">&lt;#</span> +<span class="cm"> Variables definition</span> +<span class="cm">#&gt;</span> +<span class="nv">$MaxSeconds</span> <span class="p">=</span> <span class="n">120</span> <span class="c"># Max seconds behind master allowed</span> +<span class="nv">$MysqlUser</span> <span class="p">=</span> <span class="s1">&#39;root&#39;</span> +<span class="nv">$MysqlPass</span> <span class="p">=</span> <span class="s1">&#39;&#39;</span> + +<span class="nv">$MailTo</span> <span class="p">=</span> <span class="s1">&#39;mauricio@sipmann.com&#39;</span> +<span class="nv">$MailFrom</span> <span class="p">=</span> <span class="s1">&#39;mauricio@sipmann.com&#39;</span> + + +<span class="nv">$data</span> <span class="p">=</span> <span class="p">$(</span><span class="n">mysql</span> <span class="n">-u</span> <span class="nv">$MysqlUser</span> <span class="n">-p</span><span class="s2">&quot;$MysqlPass&quot;</span> <span class="n">-e</span> <span class="s1">&#39;SHOW SLAVE STATUS \G&#39;</span><span class="p">)</span> + +<span class="c">#Debug data</span> +<span class="c">#$data = Get-Content &#39;c:\temp\sampleresult.txt&#39;</span> + +<span class="cm">&lt;# Parse the data #&gt;</span> +<span class="nv">$IORunning</span> <span class="p">=</span> <span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Slave_IO_Running:&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> +<span class="nv">$SQLRunning</span> <span class="p">=</span> <span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Slave_SQL_Running:&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> +<span class="nv">$LastErrNo</span> <span class="p">=</span> <span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Last_Errno&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> +<span class="nv">$SecondsBh</span> <span class="p">=</span> <span class="no">[int]</span><span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Seconds_Behind_Master&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> + +<span class="k">If</span> <span class="p">(</span><span class="nv">$IORunning</span> <span class="o">-Eq</span> <span class="s1">&#39;No&#39;</span> <span class="o">-Or</span> <span class="nv">$SQLRunning</span> <span class="o">-Eq</span> <span class="s1">&#39;No&#39;</span> <span class="o">-Or</span> <span class="nv">$SecondsBh</span> <span class="o">-gt</span> <span class="nv">$MaxSeconds</span><span class="p">)</span> <span class="p">{</span> + <span class="nv">$MailBody</span> <span class="p">=</span> <span class="s1">&#39;&lt;h1&gt;Problema na replicação&lt;/h1&gt;&lt;br&gt;&#39;</span> + + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39; IO Running: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$IORunning</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39; SQL Running: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$SQLRunning</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39;Seconds Behind: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$SecondsBh</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39; Last Err No: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$LastErrNo</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + + <span class="cm">&lt;# Send e-mail, maybe some telegram message here too #&gt;</span> + <span class="nb">Send-MailMessage</span> <span class="n">-To</span> <span class="nv">$MailTo</span> <span class="n">-From</span> <span class="nv">$MailFrom</span> <span class="n">-Subject</span> <span class="s1">&#39;Problemas na replicação&#39;</span> <span class="n">-bodyAsHtml</span> <span class="nv">$MailBody</span> <span class="n">-Credential</span> <span class="p">(</span><span class="nb">Get-Credential</span><span class="p">)</span> <span class="n">-SmtpServer</span> <span class="s1">&#39;smtp.office365.com&#39;</span> <span class="n">-Port</span> <span class="n">587</span> <span class="n">-UseSsl</span> +<span class="p">}</span> <span class="k">Else</span> <span class="p">{</span> + <span class="nb">Write-Host</span> <span class="s2">&quot;Up and running&quot;</span> +<span class="p">}</span> +</code></pre></div>Microsoft Against Covid2020-10-03T19:00:00-03:002020-10-03T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-03:/en/microsoft-against-covid.html<p>Has your job been affected by covid? Well, last week I've posted on <a href="https://grepora.com/2020/09/17/microsoft-ignite-certification-voucher/">Grepora</a> about a Free Certification Voucher that Microsoft was giving away at the Microsoft Ignite event. After that, I found that they were also giving a huge discount to people who have had their job affected by …</p><p>Has your job been affected by covid? Well, last week I've posted on <a href="https://grepora.com/2020/09/17/microsoft-ignite-certification-voucher/">Grepora</a> about a Free Certification Voucher that Microsoft was giving away at the Microsoft Ignite event. After that, I found that they were also giving a huge discount to people who have had their job affected by covid pandemic. </p> +<p>To see more details about if you were eligible, access <a href="https://docs.microsoft.com/en-us/learn/certifications/skillingoffer">https://docs.microsoft.com/en-us/learn/certifications/skillingoffer</a>.</p>The power of PowerShell2020-09-21T19:00:00-03:002020-09-21T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-09-21:/en/the-power-of-powershell.html<p>As a long time Linux user, I've automated a few things with bash scripts and stayed away from PowerShell... I've moved to a Windows environment a few years ago and still, haven gave a shot to PS. But why not? I've made a few scripts to automate some tasks at …</p><p>As a long time Linux user, I've automated a few things with bash scripts and stayed away from PowerShell... I've moved to a Windows environment a few years ago and still, haven gave a shot to PS. But why not? I've made a few scripts to automate some tasks at a Protheus server.</p> +<p>I found the PS scripts being easy to read and understand. Bellow, we have a script to remove files filtering their extension (or no extension at all like the following script). </p> +<div class="highlight"><pre><span></span><code><span class="nb">Get-ChildItem</span> <span class="s2">&quot;C:\TOTVS\protheus_data\system&quot;</span> <span class="o">-File</span> <span class="n">-Filter</span> <span class="p">*.</span> <span class="p">|</span> <span class="nb">Move-Item</span> <span class="n">-Force</span> <span class="n">-Destination</span> <span class="p">{</span> + <span class="cm">&lt;# Diretory where the files will be moved. You can use Date formats to help name it #&gt;</span> + <span class="cm">&lt;# LastWriteTime proprtie from the current file #&gt;</span> + <span class="nv">$dir</span> <span class="p">=</span> <span class="s2">&quot;C:\bad_files\{0:yyyy\\MM\\dd}&quot;</span> <span class="o">-f</span> <span class="nv">$_</span><span class="p">.</span><span class="n">LastWriteTime</span> + <span class="nv">$null</span> <span class="p">=</span> <span class="n">mkdir</span> <span class="nv">$dir</span> <span class="n">-Force</span> + <span class="s2">&quot;$dir\</span><span class="p">$(</span><span class="nv">$_</span><span class="p">.</span><span class="n">Name</span><span class="p">)</span><span class="s2">&quot;</span> +<span class="p">}</span> +</code></pre></div> + +<p>Have you ever been in the need to remove files based on other file content? Bello a script where I read a file that has the names of files that I want to remove. </p> +<div class="highlight"><pre><span></span><code><span class="k">foreach</span><span class="p">(</span><span class="nv">$line</span> <span class="k">in</span> <span class="nb">Get-Content</span> <span class="p">.\</span><span class="n">Desktop</span><span class="p">\</span><span class="n">bad_files</span><span class="p">.</span><span class="n">txt</span><span class="p">)</span> <span class="p">{</span> + <span class="k">if</span> <span class="p">(</span><span class="nb">Test-Path</span><span class="p">(</span><span class="s1">&#39;\\x.y.z.a\c$\TOTVS\protheus_data\xmls\&#39;</span><span class="p">+</span><span class="nv">$line</span><span class="p">+</span><span class="s1">&#39;.xml&#39;</span><span class="p">))</span> <span class="p">{</span> + <span class="nb">Remove-Item</span><span class="p">(</span><span class="s1">&#39;\\x.y.z.a\c$\TOTVS\protheus_data\xmls\&#39;</span><span class="p">+</span><span class="nv">$line</span><span class="p">+</span><span class="s1">&#39;.xml&#39;</span><span class="p">)</span> + <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> + <span class="nb">echo </span><span class="nv">$line</span> <span class="p">+</span> <span class="s1">&#39; - File not found&#39;</span> + <span class="p">}</span> +<span class="p">}</span> +</code></pre></div> + +<p>And a bonus script to stop/start services (if you handle some Protheus Server, you know why I do that).</p> +<div class="highlight"><pre><span></span><code><span class="nv">$servicesNames</span> <span class="p">=</span> <span class="s1">&#39;app_main&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker1&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker2&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker3&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker4&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker5&#39;</span> + +<span class="nb">Write-host</span> <span class="s2">&quot;Stoping Services&quot;</span> +<span class="nb">Write-host</span> <span class="s2">&quot;--------------------------&quot;</span> + +<span class="k">foreach</span> <span class="p">(</span><span class="nv">$srv</span> <span class="k">in</span> <span class="nv">$servicesNames</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Write-host</span> <span class="s2">&quot;Stopping: &quot;</span> <span class="p">+</span> <span class="nv">$srv</span> + <span class="nv">$SrvPID</span> <span class="p">=</span> <span class="p">(</span><span class="nb">get-wmiobject</span> <span class="n">win32_service</span> <span class="p">|</span> <span class="nb">where </span><span class="p">{</span> <span class="nv">$_</span><span class="p">.</span><span class="n">name</span> <span class="o">-eq</span> <span class="nv">$srv</span><span class="p">}).</span><span class="n">processID</span> + <span class="nb">Write-host</span> <span class="s2">&quot;PID: &quot;</span> <span class="p">+</span> <span class="nv">$SrvPID</span> + + <span class="cm">&lt;# Force if the proccess is stucked #&gt;</span> + <span class="nb">Stop-Process</span> <span class="nv">$SrvPID</span> <span class="n">-Force</span> + <span class="nb">Write-host</span> <span class="s2">&quot;PDI &quot;</span> <span class="p">+</span> <span class="nv">$SrvPID</span> <span class="p">+</span> <span class="s2">&quot; stopped&quot;</span> +<span class="p">}</span> + + +<span class="nb">Write-host</span> <span class="s2">&quot;Starting Services&quot;</span> +<span class="nb">Write-host</span> <span class="s2">&quot;--------------------------&quot;</span> + +<span class="k">foreach</span> <span class="p">(</span><span class="nv">$srv</span> <span class="k">in</span> <span class="nv">$servicesNames</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Write-host</span> <span class="s2">&quot;Starting: &quot;</span> <span class="p">+</span> <span class="nv">$srv</span> + <span class="nb">Start-Service</span> <span class="nv">$srv</span> +<span class="p">}</span> +</code></pre></div> + +<p>Do you have any automated script? Share with us :)</p>Top Level Statement in C# 92020-07-29T19:00:00-03:002020-07-29T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-07-29:/en/top_level_statement_csharp_9.html<p>Hey folks, I'm coming along to tell you a few things about the new feature of C# 9. Every time you want to start a new project, you always have the same Main File, with the same structure. At the next version of C# (version 9), we'll have a new …</p><p>Hey folks, I'm coming along to tell you a few things about the new feature of C# 9. Every time you want to start a new project, you always have the same Main File, with the same structure. At the next version of C# (version 9), we'll have a new feature called <code>Top Level Statement</code>. With that, we'll be able to code our app without any namespace/class/public void static main structure. Take a look at the code below.</p> +<div class="highlight"><pre><span></span><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span> + +<span class="n">Console</span><span class="p">.</span><span class="n">WriteLine</span><span class="p">(</span><span class="s">&quot;Hello World!&quot;</span><span class="p">);</span> +</code></pre></div> + +<p>It looks pretty simple, but with this, you can play around with your code, and even code a simple/tiny Web API. To start playing with the new features, firstly download the <a href="https://dotnet.microsoft.com/download/dotnet/5.0">.net 5 SDK</a> and change your <code>.csproj</code> file to target the .net 5 and language preview like bellow.</p> +<div class="highlight"><pre><span></span><code><span class="nt">&lt;Project</span> <span class="na">Sdk=</span><span class="s">&quot;Microsoft.NET.Sdk&quot;</span><span class="nt">&gt;</span> + <span class="nt">&lt;PropertyGroup&gt;</span> + <span class="nt">&lt;OutputType&gt;</span>Exe<span class="nt">&lt;/OutputType&gt;</span> + <span class="nt">&lt;TargetFramework&gt;</span>net5.0<span class="nt">&lt;/TargetFramework&gt;</span> + <span class="nt">&lt;LangVersion&gt;</span>preview<span class="nt">&lt;/LangVersion&gt;</span> + <span class="nt">&lt;/PropertyGroup&gt;</span> +<span class="nt">&lt;/Project&gt;</span> +</code></pre></div> + +<p>And you're ready to play with the awesome features available in the preview. Let's code a way to get the image of the day from NASA API and print the Picture of the Day. No awesome code here, it's really a way to show how simple a simple call could be. After here, why not save the image in a file? Maybe send the file over telegram?</p> +<div class="highlight"><pre><span></span><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Net.Http</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Text.Json</span><span class="p">;</span> + +<span class="kt">var</span> <span class="n">API</span> <span class="p">=</span> <span class="s">&quot;https://api.nasa.gov/planetary/apod?hd=true&amp;api_key=DEMO_KEY&quot;</span><span class="p">;</span> +<span class="kt">var</span> <span class="n">cli</span> <span class="p">=</span> <span class="k">new</span> <span class="n">HttpClient</span><span class="p">();</span> + +<span class="kt">var</span> <span class="n">response</span> <span class="p">=</span> <span class="k">await</span> <span class="n">cli</span><span class="p">.</span><span class="n">GetAsync</span><span class="p">(</span><span class="n">API</span><span class="p">);</span> +<span class="kt">var</span> <span class="n">data</span> <span class="p">=</span> <span class="n">JsonSerializer</span><span class="p">.</span><span class="n">Deserialize</span><span class="p">&lt;</span><span class="n">NasaApi</span><span class="p">&gt;(</span><span class="k">await</span> <span class="n">response</span><span class="p">.</span><span class="n">Content</span><span class="p">.</span><span class="n">ReadAsStringAsync</span><span class="p">());</span> + +<span class="n">Console</span><span class="p">.</span><span class="n">WriteLine</span><span class="p">(</span><span class="n">data</span><span class="p">.</span><span class="n">Url</span><span class="p">);</span> +</code></pre></div> + +<p>That's it for today folks. Keep an eye open for the awesome features C# 9 will bring to us, there's plenty more features already available.</p>Zabbix poller processes more than 75%2020-07-02T19:00:00-03:002020-07-02T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-07-02:/en/zabbix-poller-processes-more-than-75.html<p>Hey folks, this is the third post about tweaking the Zabbix configurations. All changes that I've suggested here were based on a Zabbix Server with 50+ hosts. Another thing that can happen to your server, it's the poller get overwhelmed by the amount of servers that need to be polled …</p><p>Hey folks, this is the third post about tweaking the Zabbix configurations. All changes that I've suggested here were based on a Zabbix Server with 50+ hosts. Another thing that can happen to your server, it's the poller get overwhelmed by the amount of servers that need to be polled plus the ones that are not responding. Bellow two images where you can see the log and the graphic where you can see the usage percent. </p> +<p><img alt="Dashboard log about the poller processes" src="/images/zabbix_pooler.png"></p> +<p><img alt="Graph showing the utilization percent of each collector" src="/images/zabbix_pooler_3.png"></p> +<p>To solve, let's go back to the <code>zabbix_server.conf</code> file and find two variables, <code>StartPollers</code> and <code>StartPollersUnreachable</code>. Increase them as needed. There's no magic number, you must see what works for you. But keep in mind that the <code>StartPollersUnreachable</code> is responsible for that host that can't be "reached" (of course) and will hold your poller more time.</p> +<div class="highlight"><pre><span></span><code><span class="c1">### Option: StartPollers</span> +<span class="c1"># Number of pre-forked instances of pollers.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 0-1000</span> +<span class="c1"># Default:</span> +<span class="na">StartPollers</span><span class="o">=</span><span class="s">20</span> + +<span class="c1">#...</span> + +<span class="c1">### Option: StartPollersUnreachable</span> +<span class="c1"># Number of pre-forked instances of pollers for unreachable hosts (including IPMI and Java).</span> +<span class="c1"># At least one poller for unreachable hosts must be running if regular, IPMI or Java pollers</span> +<span class="c1"># are started.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 0-1000</span> +<span class="c1"># Default:</span> +<span class="na">StartPollersUnreachable</span><span class="o">=</span><span class="s">5</span> +</code></pre></div> + +<p>After the change, restart the server and wait a few moments and take a look again at your dashboard. Bellow the effect that I've got.</p> +<p><img alt="Graph showing the new utilization percent of the processes after the changes" src="/images/zabbix_pooler_4.png"></p>Monitoring a Website heath with Azure Functions2020-06-22T19:00:00-03:002020-06-22T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-06-22:/en/monitoring-website-heath-with-azure-functions.html<p>Sometimes you get your self in need to monitor a website's health or it's content for changes. Of course, there's plenty of options out there, but for the sake of curiosity, let's code our own to see what we can do. First things first. Everything you'll see here, you can …</p><p>Sometimes you get your self in need to monitor a website's health or it's content for changes. Of course, there's plenty of options out there, but for the sake of curiosity, let's code our own to see what we can do. First things first. Everything you'll see here, you can achieve with the <a href="https://azure.microsoft.com/free/">free tier</a> of azure.</p> +<p>The main idea of our app will be to monitor website health (status code). To create a new Azure Function Project, follow the steps below.</p> +<p><img alt="Steps to create a azure function project" src="/images/azure_functions.gif"></p> +<p>After creating the project, you'll have a few files. Open your main file and start coding. The main file will have a function called <code>Run</code> and you can code your request method. I've created an <code>async</code> method to make the request and log the output at the console. The full code you can see below.</p> +<div class="highlight"><pre><span></span><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Linq</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Net.Http</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Threading.Tasks</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">Microsoft.Azure.WebJobs</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">Microsoft.Azure.WebJobs.Host</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">Microsoft.Extensions.Logging</span><span class="p">;</span> + +<span class="k">namespace</span> <span class="nn">Sipmann.CheckMySite</span> +<span class="p">{</span> + <span class="k">public</span> <span class="k">static</span> <span class="k">class</span> <span class="nc">HttpCheck</span> + <span class="p">{</span> + + <span class="k">private</span> <span class="k">static</span> <span class="k">async</span> <span class="n">Task</span> <span class="nf">GetTask</span><span class="p">(</span><span class="kt">string</span> <span class="n">url</span><span class="p">,</span> <span class="n">ILogger</span> <span class="n">log</span><span class="p">)</span> + <span class="p">{</span> + <span class="kt">var</span> <span class="n">request</span> <span class="p">=</span> <span class="k">new</span> <span class="n">HttpRequestMessage</span><span class="p">(</span><span class="n">HttpMethod</span><span class="p">.</span><span class="n">Get</span><span class="p">,</span> <span class="n">url</span><span class="p">);</span> + + <span class="kt">var</span> <span class="n">client</span> <span class="p">=</span> <span class="k">new</span> <span class="n">HttpClient</span><span class="p">();</span> + <span class="kt">var</span> <span class="n">response</span> <span class="p">=</span> <span class="k">await</span> <span class="n">client</span><span class="p">.</span><span class="n">SendAsync</span><span class="p">(</span><span class="n">request</span><span class="p">);</span> + + <span class="k">if</span> <span class="p">(</span><span class="n">response</span><span class="p">.</span><span class="n">IsSuccessStatusCode</span><span class="p">)</span> + <span class="p">{</span> + <span class="n">log</span><span class="p">.</span><span class="n">LogInformation</span><span class="p">(</span><span class="err">$</span><span class="s">&quot;URL ${url} esta OK&quot;</span><span class="p">);</span> + <span class="p">}</span> + <span class="k">else</span> + <span class="p">{</span> + <span class="n">log</span><span class="p">.</span><span class="n">LogInformation</span><span class="p">(</span><span class="err">$</span><span class="s">&quot;URL ${url} não esta OK&quot;</span><span class="p">);</span> + <span class="p">}</span> + <span class="p">}</span> + +<span class="na"> [FunctionName(&quot;HttpCheck&quot;)]</span> + <span class="k">public</span> <span class="k">static</span> <span class="k">void</span> <span class="nf">Run</span><span class="p">([</span><span class="n">TimerTrigger</span><span class="p">(</span><span class="s">&quot;0 */5 * * * *&quot;</span><span class="p">)]</span><span class="n">TimerInfo</span> <span class="n">myTimer</span><span class="p">,</span> <span class="n">ILogger</span> <span class="n">log</span><span class="p">)</span> + <span class="p">{</span> + <span class="kt">var</span> <span class="n">urls</span> <span class="p">=</span> <span class="k">new</span><span class="p">[]{</span><span class="s">&quot;https://www.sipmann.com&quot;</span><span class="p">,</span> <span class="s">&quot;https://www.canezecanez.com.br&quot;</span><span class="p">};</span> + + <span class="c1">// Start every request and wait for them all to complete</span> + <span class="n">Task</span><span class="p">.</span><span class="n">WaitAll</span><span class="p">(</span><span class="n">urls</span><span class="p">.</span><span class="n">Select</span><span class="p">(</span><span class="n">url</span> <span class="p">=&gt;</span> <span class="n">GetTask</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">log</span><span class="p">)).</span><span class="n">ToArray</span><span class="p">());</span> + <span class="n">log</span><span class="p">.</span><span class="n">LogInformation</span><span class="p">(</span><span class="err">$</span><span class="s">&quot;Finalizou a fila&quot;</span><span class="p">);</span> + <span class="p">}</span> + <span class="p">}</span> +<span class="p">}</span> +</code></pre></div> + +<p>Now you can enhance the function and maybe send some alerts like a Telegram message when one of your sites went down.</p>Azure Data Fundamentals certification with 80% discount2020-06-09T12:30:00-03:002020-06-09T12:30:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-06-09:/en/azure-data-fundamentals-certification-80-discount.html<p>Hey folks, if you want to achieve some certification this year, keep an eye open for vouchers. A few months ago, Oracle released a set of free courses with certifications. Now it's Microsoft time. Microsoft is updating they're certifications and we have a voucher of 80% discount using the coupon …</p><p>Hey folks, if you want to achieve some certification this year, keep an eye open for vouchers. A few months ago, Oracle released a set of free courses with certifications. Now it's Microsoft time. Microsoft is updating they're certifications and we have a voucher of 80% discount using the coupon <strong>DP900Norfolk</strong> at the checkout of the beta certification DP-900. </p> +<p>Be aware that this certification is in beta and the result won't be instantly available as the regular ones. Access the following link and schedule your exam. <a href="https://docs.microsoft.com/pt-br/learn/certifications/exams/dp-900" target="_blank">https://docs.microsoft.com/pt-br/learn/certifications/exams/dp-900</a>.</p> +<p><strong>Update:</strong> There is a 80% voucher also for <a href="https://docs.microsoft.com/en-us/learn/certifications/azure-ai-fundamentals" target="_blank">https://docs.microsoft.com/en-us/learn/certifications/azure-ai-fundamentals</a>. Voucher: <strong>AI900Saratoga</strong></p>Zabbix ICMP pinger processes more than 75%2020-05-25T16:00:00-03:002020-05-25T16:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-05-25:/en/zabbix-icmp-pinger-processes-more-than-75.html<p>So your monitoring sytems have grown and your zabbix started loggin "Zabbix icmp pinger processes more than 75% busy" at the dashboard.</p> +<p><img alt="Dashboard do zabbix avisando sobre o erro" src="/images/zabbix_pinger01.png"></p> +<p>All you have to do is open your config file (<code>/etc/zabbix/zabbix_server.conf</code>) and find the a tag named <code>StartPingers</code>. It'll be commented by default. Uncomment it …</p><p>So your monitoring sytems have grown and your zabbix started loggin "Zabbix icmp pinger processes more than 75% busy" at the dashboard.</p> +<p><img alt="Dashboard do zabbix avisando sobre o erro" src="/images/zabbix_pinger01.png"></p> +<p>All you have to do is open your config file (<code>/etc/zabbix/zabbix_server.conf</code>) and find the a tag named <code>StartPingers</code>. It'll be commented by default. Uncomment it and set it's value to something like 3 or 4. It should solve your problem.</p> +<div class="highlight"><pre><span></span><code><span class="c1">### Option: StartPingers</span> +<span class="c1"># Number of pre-forked instances of ICMP pingers.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 0-1000</span> +<span class="c1"># Default:</span> +<span class="nv">StartPingers</span><span class="o">=</span><span class="m">4</span> +</code></pre></div> + +<h2>How many Pingers do I need?</h2> +<p>Well, there is no exact answer to this. If you set it too high, you'll be wasting resources. The best way to solve, it's increasing them as soon as you notice the percentage growing.</p>Zabbix Server Out of Memory2020-02-27T19:00:00-03:002020-02-27T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-02-27:/en/zabbix-server-out-of-memory-crash.html<p>Do you have a crashing Zabbix Server and looking through the log <code>/var/log/zabbix/zabbix_server.log</code> you see the following out of memory message?</p> +<div class="highlight"><pre><span></span><code>__mem_malloc: skipped <span class="m">0</span> asked <span class="m">24</span> skip_min <span class="m">18446744073709551615</span> skip_max <span class="m">0</span> +<span class="o">[</span>file:dbconfig.c,line:94<span class="o">]</span> __zbx_mem_realloc<span class="o">()</span>: out of memory <span class="o">(</span>requested <span class="m">16</span> bytes<span class="o">)</span> +<span class="o">[</span>file:dbconfig.c,line …</code></pre></div><p>Do you have a crashing Zabbix Server and looking through the log <code>/var/log/zabbix/zabbix_server.log</code> you see the following out of memory message?</p> +<div class="highlight"><pre><span></span><code>__mem_malloc: skipped <span class="m">0</span> asked <span class="m">24</span> skip_min <span class="m">18446744073709551615</span> skip_max <span class="m">0</span> +<span class="o">[</span>file:dbconfig.c,line:94<span class="o">]</span> __zbx_mem_realloc<span class="o">()</span>: out of memory <span class="o">(</span>requested <span class="m">16</span> bytes<span class="o">)</span> +<span class="o">[</span>file:dbconfig.c,line:94<span class="o">]</span> __zbx_mem_realloc<span class="o">()</span>: please increase CacheSize configuration parameter +</code></pre></div> + +<p>Besides the clear solution to the error, that's a common issue on servers that have a few monitoring items on it (servers, switches, firewalls, databases, etc...). To solve, go to your zabbix_server.conf and look for the CacheSize property and set it to a higher value. Its default should be 8M. At a customer that has somewhere between 4 servers, 7 firewalls/appliances, and a few other things, a 32M did the job, but you can set up to 8G.</p> +<p>See ya folks.</p>Flutter + firebase auth crashing2019-10-03T19:00:00-03:002019-10-03T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2019-10-03:/en/flutter_with_firebase_auth_crashing.html<p>Hey Folks, recently I've started learning <a href="https://flutter.dev/">Flutter</a> and right after a TODO List, I tried a Firebase integration. But as soon as I started setting the dependencies, my app stopped opening... just a crash. After a few logs digging, I've found the following log.</p> +<div class="highlight"><pre><span></span><code>AndroidRuntime: FATAL EXCEPTION: main +AndroidRuntime: Process …</code></pre></div><p>Hey Folks, recently I've started learning <a href="https://flutter.dev/">Flutter</a> and right after a TODO List, I tried a Firebase integration. But as soon as I started setting the dependencies, my app stopped opening... just a crash. After a few logs digging, I've found the following log.</p> +<div class="highlight"><pre><span></span><code>AndroidRuntime: FATAL EXCEPTION: main +AndroidRuntime: Process: com.example.diadocasal, PID: <span class="m">13672</span> +AndroidRuntime: java.lang.NoClassDefFoundError: Failed resolution of: Landroid/support/v4/util/ArrayMap<span class="p">;</span> +AndroidRuntime: at com.google.android.gms.internal.measurement.zzca.&lt;clinit&gt;<span class="o">(</span>Unknown Source:60<span class="o">)</span> +AndroidRuntime: at com.google.android.gms.internal.measurement.zzcm.zzr<span class="o">(</span>Unknown Source:7<span class="o">)</span> +AndroidRuntime: at com.google.android.gms.measurement.internal.zzfj.&lt;init&gt;<span class="o">(</span>Unknown Source:23<span class="o">)</span> +</code></pre></div> + +<p>Notice the "NoClassDefFound" of an ArrayMap. To solve that I did the following changes to the files:</p> +<div class="highlight"><pre><span></span><code><span class="c1">//build.gradle file</span> + <span class="n">ext</span><span class="p">.</span><span class="na">kotlin_version</span> <span class="o">=</span> <span class="err">&#39;</span><span class="mf">1.3.20</span><span class="err">&#39;</span> +<span class="o">[</span><span class="p">...</span><span class="o">]</span> + <span class="n">dependencies</span> <span class="p">{</span> + <span class="n">classpath</span> <span class="err">&#39;</span><span class="n">com</span><span class="p">.</span><span class="na">android</span><span class="p">.</span><span class="na">tools</span><span class="p">.</span><span class="na">build</span><span class="p">:</span><span class="n">gradle</span><span class="p">:</span><span class="mf">3.3.0</span><span class="err">&#39;</span> <span class="c1">// gradle version</span> +</code></pre></div> + +<div class="highlight"><pre><span></span><code><span class="c1">;gradle.properties file</span> +<span class="na">org.gradle.jvmargs</span><span class="o">=</span><span class="s">-Xmx1536M ;mine have just this line at first</span> +<span class="na">android.useAndroidX</span><span class="o">=</span><span class="s">true ; uses androidX instead of the default support library</span> +<span class="na">android.enableJetifier</span><span class="o">=</span><span class="s">true ; uses jetpack libraries</span> +<span class="na">android.enableR8</span><span class="o">=</span><span class="s">true ; the new code shriker</span> +</code></pre></div> + +<p>After that, voilà, app up and running.</p>Removing a user from SQL Server database who owns a schema2019-09-06T07:00:00-03:002020-10-21T18:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2019-09-06:/en/removing-user-from-sql-server-database.html<p>Your customer urge you to drop a user from the MsSQL Server database, but you stuck with the following related error:</p> +<div class="highlight"><pre><span></span><code><span class="n">Error</span><span class="o">:</span> <span class="mi">15138</span> <span class="n">The</span> <span class="n">database</span> <span class="n">principal</span> <span class="n">owns</span> <span class="n">a</span> <span class="n">schema</span> <span class="k">in</span> <span class="n">the</span> <span class="n">database</span><span class="o">,</span> <span class="n">and</span> <span class="n">cannot</span> <span class="n">be</span> <span class="n">dropped</span><span class="o">.</span> +</code></pre></div> + +<p>That means that the user owns one or more shcemas of your database. If …</p><p>Your customer urge you to drop a user from the MsSQL Server database, but you stuck with the following related error:</p> +<div class="highlight"><pre><span></span><code><span class="n">Error</span><span class="o">:</span> <span class="mi">15138</span> <span class="n">The</span> <span class="n">database</span> <span class="n">principal</span> <span class="n">owns</span> <span class="n">a</span> <span class="n">schema</span> <span class="k">in</span> <span class="n">the</span> <span class="n">database</span><span class="o">,</span> <span class="n">and</span> <span class="n">cannot</span> <span class="n">be</span> <span class="n">dropped</span><span class="o">.</span> +</code></pre></div> + +<p>That means that the user owns one or more shcemas of your database. If you don't have access to the SSMS to see which schema or objects the user owns, the following SQL should do the job.</p> +<div class="highlight"><pre><span></span><code><span class="k">USE</span><span class="w"> </span><span class="o">[</span><span class="n">DATABASENAME</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> + +<span class="k">select</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Objeto</span><span class="p">,</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Owner</span><span class="w"></span> +<span class="k">from</span><span class="w"> </span><span class="n">sys</span><span class="p">.</span><span class="n">schemas</span><span class="w"> </span><span class="n">so</span><span class="w"></span> +<span class="k">inner</span><span class="w"> </span><span class="k">join</span><span class="w"> </span><span class="n">sysusers</span><span class="w"> </span><span class="n">su</span><span class="w"> </span><span class="k">on</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">principal_id</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">uid</span><span class="w"></span> +<span class="k">where</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">&#39;username&#39;</span><span class="w"></span> + +<span class="k">select</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Objeto</span><span class="p">,</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Owner</span><span class="p">,</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">xtype</span><span class="w"> </span><span class="n">Tipo</span><span class="w"></span> +<span class="k">from</span><span class="w"> </span><span class="n">sys</span><span class="p">.</span><span class="n">sysobjects</span><span class="w"> </span><span class="n">so</span><span class="w"></span> +<span class="k">inner</span><span class="w"> </span><span class="k">join</span><span class="w"> </span><span class="n">sysusers</span><span class="w"> </span><span class="n">su</span><span class="w"> </span><span class="k">on</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">uid</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">uid</span><span class="w"></span> +<span class="k">where</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">&#39;username&#39;</span><span class="w"></span> +</code></pre></div> + +<p>Once you have the objects/schemas owned by the user, you can change them with the following SQL (schema change sample):</p> +<div class="highlight"><pre><span></span><code><span class="k">USE</span><span class="w"> </span><span class="o">[</span><span class="n">DATABASENAME</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +<span class="k">ALTER</span><span class="w"> </span><span class="k">AUTHORIZATION</span><span class="w"> </span><span class="k">ON</span><span class="w"> </span><span class="k">SCHEMA</span><span class="o">::[</span><span class="n">db_datareader</span><span class="o">]</span><span class="w"> </span><span class="k">TO</span><span class="w"> </span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="w"> </span><span class="c1">-- new owner username</span> +<span class="k">ALTER</span><span class="w"> </span><span class="k">AUTHORIZATION</span><span class="w"> </span><span class="k">ON</span><span class="w"> </span><span class="k">SCHEMA</span><span class="o">::[</span><span class="n">db_datawriter</span><span class="o">]</span><span class="w"> </span><span class="k">TO</span><span class="w"> </span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +</code></pre></div> + +<p>Then you're ready to drop the user <code>DROP USER [username]</code></p> +<h2>How to list all the schemas and it's owners?</h2> +<p>Here's a script to list schemas and it's owners.</p> +<div class="highlight"><pre><span></span><code><span class="k">USE</span><span class="w"> </span><span class="o">[</span><span class="n">DATABASENAME</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +<span class="k">SELECT</span><span class="w"></span> +<span class="w"> </span><span class="nf">schema_name</span><span class="p">(</span><span class="nf">schema_id</span><span class="p">)</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="n">schemaname</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="nf">user_name</span><span class="p">(</span><span class="n">schm</span><span class="p">.</span><span class="n">principal_id</span><span class="p">)</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="n">username</span><span class="p">,</span><span class="w"> </span><span class="o">*</span><span class="w"></span> +<span class="k">FROM</span><span class="w"> </span><span class="n">sys</span><span class="p">.</span><span class="n">schemas</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="n">schm</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +</code></pre></div>Limiting Connection Resources on SQL Server2019-08-12T12:00:00-03:002019-08-12T12:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2019-08-12:/en/limiting-connection-resources-sql-server.html<p>Have you ever suffered from a slow SQLServer database? Someone love to run that heavy query in the database? Resource Governor to the rescue. You can set a few rules on how users (connections actually) will use the server/database resources based on a few things.</p> +<p>First things first, if …</p><p>Have you ever suffered from a slow SQLServer database? Someone love to run that heavy query in the database? Resource Governor to the rescue. You can set a few rules on how users (connections actually) will use the server/database resources based on a few things.</p> +<p>First things first, if you don't have DAC enabled, enable it now. Dealing with resource governor can lock you out of the database and leave you without action (almost... you can start the server with -c -m -f).</p> +<p>Now to understand how Resource Governor works, we have a few keywords <code>resource pool</code>, <code>workload group</code> e <code>Classifier Function</code>.</p> +<p><img alt="Pool Sample" src="/images/sql-pool.png"></p> +<h2>Resource Pool</h2> +<p>First, we have the Resource Pool, with is the bigger resource group that we have the ability to manage. With it, we can set a few things like: <code>MIN_CPU_PERCENT</code>, <code>MAX_CPU_PERCENT</code>, <code>MIN_MEMORY_PERCENT</code>, <code>MAX_MEMORY_PERCENT</code>, <code>MIN_IOPS_PER_VOLUME</code>, and <code>MAX_IOPS_PER_VOLUME</code>.</p> +<p>Be aware that the <code>MAX_CPU_PERCENT</code> will just "works" when there is another connection with a higher priority, otherwise it will use what is available. Let's create a pool.</p> +<div class="highlight"><pre><span></span><code><span class="k">CREATE</span><span class="w"> </span><span class="n">RESOURCE</span><span class="w"> </span><span class="n">POOL</span><span class="w"> </span><span class="o">[</span><span class="n">SpreadSheet</span><span class="o">]</span><span class="w"></span> +<span class="k">WITH</span><span class="w"> </span><span class="p">(</span><span class="w"></span> +<span class="w"> </span><span class="n">MIN_CPU_PERCENT</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">MAX_CPU_PERCENT</span><span class="o">=</span><span class="mi">20</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">MIN_MEMORY_PERCENT</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">MAX_MEMORY_PERCENT</span><span class="o">=</span><span class="mi">20</span><span class="w"></span> +<span class="p">);</span><span class="w"></span> +</code></pre></div> + +<p>## Workload Group</p> +<p>Then we have a workload group that "works" inside a pool, so you can have another granularity on how you can split your resources. Again, we have a few options: <code>IMPORTANCE</code>, <code>REQUEST_MAX_CPU_TIME_SEC</code>, <code>REQUEST_MAX_MEMORY_GRANT_PERCENT</code>, <code>GROUP_MAX_REQUESTS</code>.</p> +<p>The <code>IMPORTANCE</code> set guesses what... the importance of that workload inside the pool, you can set LOW, MEDIUM, HIGH. GROUP_MAX_REQUESTS sets how many requests can run at the same time inside that workload (0 will set as NO LIMIT)</p> +<div class="highlight"><pre><span></span><code><span class="k">CREATE</span><span class="w"> </span><span class="n">WORKLOAD</span><span class="w"> </span><span class="k">GROUP</span><span class="w"> </span><span class="o">[</span><span class="n">DepartmentA</span><span class="o">]</span><span class="w"> </span> +<span class="k">WITH</span><span class="w"> </span><span class="p">(</span><span class="w"></span> +<span class="w"> </span><span class="n">GROUP_MAX_REQUESTS</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">IMPORTANCE</span><span class="o">=</span><span class="n">LOW</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">REQUEST_MAX_CPU_TIME_SEC</span><span class="o">=</span><span class="mi">10</span><span class="p">,</span><span class="w"> </span><span class="c1">-- Time running/using CPU</span> +<span class="w"> </span><span class="n">REQUEST_MAX_MEMORY_GRANT_PERCENT</span><span class="o">=</span><span class="mi">15</span><span class="w"></span> +<span class="p">)</span><span class="w"> </span><span class="k">USING</span><span class="w"> </span><span class="o">[</span><span class="n">SpreadSheet</span><span class="o">]</span><span class="p">;</span><span class="w"> </span><span class="c1">-- pool name here</span> +</code></pre></div> + +<h2>Classifier Function</h2> +<p>This is where everything begins... This is the entry point where you should set the group name. It's a function that will run for every new connection so be aware that if your function runs lots of queries or some heavy stuff... that time will be added to the connection handshake. If the function returns NULL or a group name that doesn't exist, the 'default' group will be used... Yes, there is a default workload group where everything runs where there's no classifier.</p> +<div class="highlight"><pre><span></span><code><span class="k">CREATE</span><span class="w"> </span><span class="k">FUNCTION</span><span class="w"> </span><span class="n">fnClassWorkloadGovernor</span><span class="p">()</span><span class="w"> </span> +<span class="k">RETURNS</span><span class="w"> </span><span class="n">SYSNAME</span><span class="w"> </span><span class="k">WITH</span><span class="w"> </span><span class="n">SCHEMABINDING</span><span class="w"> </span> +<span class="k">AS</span><span class="w"> </span> +<span class="k">BEGIN</span><span class="w"> </span> +<span class="w"> </span><span class="k">IF</span><span class="w"> </span><span class="nf">APP_NAME</span><span class="p">()</span><span class="w"> </span><span class="ow">LIKE</span><span class="w"> </span><span class="s1">&#39;%Excel%&#39;</span><span class="w"></span> +<span class="w"> </span><span class="k">RETURN</span><span class="w"> </span><span class="s1">&#39;DepartmentA&#39;</span><span class="w"></span> + +<span class="w"> </span><span class="k">IF</span><span class="w"> </span><span class="nf">HOST_NAME</span><span class="p">()</span><span class="w"> </span><span class="ow">LIKE</span><span class="w"> </span><span class="s1">&#39;%THAT_MACHINE_OR_APP_SERVER%&#39;</span><span class="w"></span> +<span class="w"> </span><span class="k">RETURN</span><span class="w"> </span><span class="s1">&#39;LowPriority&#39;</span><span class="w"></span> + +<span class="w"> </span><span class="k">RETURN</span><span class="w"> </span><span class="k">NULL</span><span class="w"></span> +<span class="k">END</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> + +<span class="k">ALTER</span><span class="w"> </span><span class="n">RESOURCE</span><span class="w"> </span><span class="n">GOVERNOR</span><span class="w"> </span><span class="k">WITH</span><span class="w"> </span><span class="p">(</span><span class="n">CLASSIFIER_FUNCTION</span><span class="o">=</span><span class="n">dbo</span><span class="p">.</span><span class="n">fnClassWorkloadGovernor</span><span class="p">);</span><span class="w"></span> +<span class="k">ALTER</span><span class="w"> </span><span class="n">RESOURCE</span><span class="w"> </span><span class="n">GOVERNOR</span><span class="w"> </span><span class="k">RECONFIGURE</span><span class="p">;</span><span class="w"></span> +</code></pre></div> + +<p>There you go... now you have a fully working resource governor, but look out that If you want to delete that classifier function, first you have to remove it from the resource governor (look the SCHEMABINDING at the create up there).</p> +<p>To disable Resource Governor</p> +<div class="highlight"><pre><span></span><code><span class="k">ALTER</span><span class="w"> </span><span class="n">RESOURCE</span><span class="w"> </span><span class="n">GOVERNOR</span><span class="w"> </span><span class="k">WITH</span><span class="w"> </span><span class="p">(</span><span class="n">CLASSIFIER_FUNCTION</span><span class="o">=</span><span class="k">null</span><span class="p">)</span><span class="w"></span> +<span class="k">ALTER</span><span class="w"> </span><span class="n">RESOURCE</span><span class="w"> </span><span class="n">GOVERNOR</span><span class="w"> </span><span class="k">RECONFIGURE</span><span class="w"></span> + +<span class="k">ALTER</span><span class="w"> </span><span class="n">RESOURCE</span><span class="w"> </span><span class="n">GOVERNOR</span><span class="w"> </span><span class="n">DISABLE</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +</code></pre></div>Using git hooks to easy your life2019-07-30T20:00:00-03:002019-07-30T20:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2019-07-30:/en/using_git_hooks_easy_your_life.html<p>Hey folks, it's been a time since my last post. In the meantime, I moved to another state, changed job, and started learning new kinds of stuff. Today I would like to share one thing that I usually do with my small git projects. Git has many cool features, git …</p><p>Hey folks, it's been a time since my last post. In the meantime, I moved to another state, changed job, and started learning new kinds of stuff. Today I would like to share one thing that I usually do with my small git projects. Git has many cool features, git hooks were one of them. I'll talk about the pre-commit hook today.</p> +<p>Let's say that, for some reason, you don't have a CI tool/server running after every commit and you want to enforce that every developer runs the tests before every commit? Git pre-commit to the rescue. You can code the hooks with shell, ruby, python, and I could be wrong, but even PHP would work. pre-commit is a client-side hook (we have server side too) and he's located inside the <cite>.git/hooks</cite> folder. Let's jump to the code... Create a file called 'pre-commit' inside that folder with the following code.</p> +<div class="highlight"><pre><span></span><span class="ch">#!/bin/bash</span> +npm <span class="nb">test</span> <span class="c1"># assuming you&#39;re using it inside a nodeJS project</span> +</pre></div> +<p>Don't forget to make the script executable!! Now break your test and try to commit. That's easy but can save you from breaking the tests at the main CI/Travis/Codeship/etc and being notified by email :). Why not even validate the lint of your project or check if the coverage doesn't fall? Does your team/company have a patter for commit messages? No problem, there is a hook called <cite>commit-msg</cite> that you can use to validate your message.</p> +Microservices with NodeJS, Express.js and RabbitMQ Part 22018-04-13T13:00:00-03:002018-04-13T13:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-04-13:/en/microservices_nodejs_express_rabbitmq_part_2.html<p>If you haven't read the <a class="reference external" href="https://www.sipmann.com/microservices_nodejs_express_rabbitmq_part_1-en.html">part 1</a> go ahead and read it... It can be useful :). Or if for some reason you want to start now, you can grab the project where we stopped <a class="reference external" href="https://github.com/sipmann/imagecompacter/releases/tag/v1">here</a> and get along. On this part, we'll implement the RabbitMQ queue and see how we …</p><p>If you haven't read the <a class="reference external" href="https://www.sipmann.com/microservices_nodejs_express_rabbitmq_part_1-en.html">part 1</a> go ahead and read it... It can be useful :). Or if for some reason you want to start now, you can grab the project where we stopped <a class="reference external" href="https://github.com/sipmann/imagecompacter/releases/tag/v1">here</a> and get along. On this part, we'll implement the RabbitMQ queue and see how we can get the best of our app and server with that.</p> +<p>Before we began coding, let's understand why we are going to use RabbitMQ if what we have now works? If you check again, you'll see how long it takes to answer the request with the optimized image. It takes a few seconds, so imagine an online service with thousands of request to optimize images (like <a class="reference external" href="https://tinypng.com/">TinyPNG</a>) how long is it gonna take to answer every request? How much of your server is it gonna take? With only one service running, probably the server will crash.</p> +<p>With a queue, we can schedule the requests so we can use the amount of memory and processor that our server has, without taking more than we can. It's better to take a few seconds to answer the request then throw some error to the user. Want more? With RabbitMQ we can see how the queue is doing and we can add more consumers (workers) to it and get things done quicker and distribute the job.</p> +<p>First of all, we need an up and running Rabbit server, for the sake of simplicity, I'll use a Docker container with it inside.</p> +<div class="highlight"><pre><span></span>docker run -d --name rabbit -p <span class="m">5672</span>:5672 -p <span class="m">8080</span>:15672 rabbitmq:3-management +</pre></div> +<p>You can see that we're running the rabbitmq:3-management image, which provides us a web interface to see how things are going. After that, if you look at our code you'll see that all the job is made at the '/upload' route, and that's what we'll change.</p> +<p>First, we need to understand what we need from RabbitMQ. We need something that, we send an image to a queue and get an optimized image back from that. There is a name for that, is RPC (remote procedure call) and there are two ways of doing this with rabbit. Both the ways you can see on their tutorial page. We'll use the approach that uses a global channel whose id is randomly generated (you'll use the name 'amq.rabbitmq.reply-to' but the rabbit will do the job).</p> +<p>Let's start importing the library, defining a few variables and defining a init function that will establish a connection with the rabbit server and create our RPC queue. The RPC queue it's where we'll receive the answer from the consumer (our worker).</p> +<div class="highlight"><pre><span></span><span class="c1">//import the library</span> +<span class="kr">const</span> <span class="nx">amqplib</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;amqplib&#39;</span><span class="p">);</span> + +<span class="c1">//queue channel</span> +<span class="kd">let</span> <span class="nx">channel</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span> +<span class="c1">//queue name</span> +<span class="kr">const</span> <span class="nx">QUEUE</span> <span class="o">=</span> <span class="s1">&#39;optimizeimg&#39;</span><span class="p">;</span> + +<span class="c1">//...</span> + +<span class="kd">function</span> <span class="nx">init</span><span class="p">()</span> <span class="p">{</span> + <span class="k">return</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;amqplib&#39;</span><span class="p">).</span><span class="nx">connect</span><span class="p">(</span><span class="s1">&#39;amqp://localhost&#39;</span><span class="p">)</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">conn</span> <span class="p">=&gt;</span> <span class="nx">conn</span><span class="p">.</span><span class="nx">createChannel</span><span class="p">())</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">ch</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="nx">channel</span> <span class="o">=</span> <span class="nx">ch</span><span class="p">;</span> + + <span class="c1">//this queue is a &quot;Direct reply-to&quot; read more at the docs</span> + <span class="c1">//When some msg comes in, we &quot;emit&quot; a message to the proper &quot;correlationId&quot; listener</span> + <span class="nx">ch</span><span class="p">.</span><span class="nx">consume</span><span class="p">(</span><span class="s1">&#39;amq.rabbitmq.reply-to&#39;</span><span class="p">,</span> <span class="nx">msg</span> <span class="p">=&gt;</span> <span class="nx">eventEmitter</span><span class="p">.</span><span class="nx">emit</span><span class="p">(</span><span class="nx">msg</span><span class="p">.</span><span class="nx">properties</span><span class="p">.</span><span class="nx">correlationId</span><span class="p">,</span> <span class="nx">msg</span><span class="p">.</span><span class="nx">content</span><span class="p">),</span> <span class="p">{</span><span class="nx">noAck</span><span class="o">:</span> <span class="kc">true</span><span class="p">});</span> + <span class="p">});</span> +<span class="p">}</span> + +<span class="c1">//Random id generator</span> +<span class="kd">function</span> <span class="nx">randomid</span><span class="p">()</span> <span class="p">{</span> + <span class="k">return</span> <span class="k">new</span> <span class="nb">Date</span><span class="p">().</span><span class="nx">getTime</span><span class="p">().</span><span class="nx">toString</span><span class="p">()</span> <span class="o">+</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">random</span><span class="p">().</span><span class="nx">toString</span><span class="p">()</span> <span class="o">+</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">random</span><span class="p">().</span><span class="nx">toString</span><span class="p">();</span> +<span class="p">}</span> + +<span class="nx">app</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="s1">&#39;/upload&#39;</span><span class="p">,</span> <span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="kd">let</span> <span class="nx">img</span> <span class="o">=</span> <span class="nx">req</span><span class="p">.</span><span class="nx">files</span><span class="p">.</span><span class="nx">image</span><span class="p">;</span> + + <span class="kd">let</span> <span class="nx">id</span> <span class="o">=</span> <span class="nx">randomid</span><span class="p">();</span> + + <span class="c1">//Event listener that will fire when the proper randomid is provided</span> + <span class="nx">eventEmitter</span><span class="p">.</span><span class="nx">once</span><span class="p">(</span><span class="nx">id</span><span class="p">,</span> <span class="nx">msg</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="nx">res</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="nx">msg</span><span class="p">,</span> <span class="s1">&#39;binary&#39;</span><span class="p">);</span> + <span class="nx">res</span><span class="p">.</span><span class="nx">end</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="s1">&#39;binary&#39;</span><span class="p">);</span> + <span class="p">});</span> + + <span class="c1">//Checks if the queue exists, and create it if needed.</span> + <span class="nx">channel</span><span class="p">.</span><span class="nx">assertQueue</span><span class="p">(</span><span class="nx">QUEUE</span><span class="p">)</span> + <span class="c1">//Sent the buffered img to the queue with the ID and the responseQueue</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="nx">channel</span><span class="p">.</span><span class="nx">sendToQueue</span><span class="p">(</span><span class="nx">QUEUE</span><span class="p">,</span> <span class="nx">img</span><span class="p">.</span><span class="nx">data</span><span class="p">,</span> <span class="p">{</span><span class="nx">correlationId</span><span class="o">:</span><span class="nx">id</span><span class="p">,</span> <span class="nx">replyTo</span><span class="o">:</span> <span class="s1">&#39;amq.rabbitmq.reply-to&#39;</span><span class="p">}));</span> + +<span class="p">});</span> + +<span class="c1">//Finally start the app with the given port number</span> +<span class="c1">//now we initialize the rabbitmq connection before start the server</span> +<span class="nx">init</span><span class="p">()</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="nx">app</span><span class="p">.</span><span class="nx">listen</span><span class="p">(</span><span class="mi">4000</span><span class="p">,</span> <span class="p">()</span> <span class="p">=&gt;</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;Example app listening on port 4000!&#39;</span><span class="p">)))</span> + <span class="p">.</span><span class="k">catch</span><span class="p">(</span><span class="nx">err</span><span class="p">=&gt;</span><span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="nx">err</span><span class="p">));</span> +</pre></div> +<p>Ok, now we have our server code rewritten so let's see our worker code. Create a file named 'worker.js' and let's see how it's gonna be. It's really simple. You initialize a connection with RabbitMQ too, create a channel, check if the queue exists and start watching for incoming messages. When an image arrives, we do the job with it and send back to the &quot;replyTo&quot; queue the optimized image for the proper sender (correlationId). In the end, we do an acknowledge of the message so it get's out from the queue.</p> +<div class="highlight"><pre><span></span><span class="kr">const</span> <span class="nx">imagemin</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;imagemin&#39;</span><span class="p">);</span> +<span class="kr">const</span> <span class="nx">imageminPngquant</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;imagemin-pngquant&#39;</span><span class="p">);</span> + +<span class="kd">let</span> <span class="nx">channel</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span> +<span class="kr">const</span> <span class="nx">QUEUE</span> <span class="o">=</span> <span class="s1">&#39;imgqueue&#39;</span><span class="p">;</span> + +<span class="nx">require</span><span class="p">(</span><span class="s1">&#39;amqplib&#39;</span><span class="p">).</span><span class="nx">connect</span><span class="p">(</span><span class="s1">&#39;amqp://localhost&#39;</span><span class="p">)</span> +<span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">conn</span> <span class="p">=&gt;</span><span class="nx">conn</span><span class="p">.</span><span class="nx">createChannel</span><span class="p">())</span> +<span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">ch</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="nx">ch</span><span class="p">.</span><span class="nx">assertQueue</span><span class="p">(</span><span class="nx">QUEUE</span><span class="p">)</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="c1">//Watch incomming messages</span> + <span class="nx">ch</span><span class="p">.</span><span class="nx">consume</span><span class="p">(</span><span class="nx">QUEUE</span><span class="p">,</span> <span class="nx">msg</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="nx">imagemin</span><span class="p">.</span><span class="nx">buffer</span><span class="p">(</span><span class="nx">msg</span><span class="p">.</span><span class="nx">content</span><span class="p">,</span> <span class="p">{</span> + <span class="nx">plugins</span><span class="o">:</span> <span class="p">[</span><span class="nx">imageminPngquant</span><span class="p">()]</span> + <span class="p">})</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">out</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="c1">//Send back to the sender (replyTo) queue and give the correlationId back</span> + <span class="c1">//so we can emit the event.</span> + <span class="nx">ch</span><span class="p">.</span><span class="nx">sendToQueue</span><span class="p">(</span><span class="nx">msg</span><span class="p">.</span><span class="nx">properties</span><span class="p">.</span><span class="nx">replyTo</span><span class="p">,</span> <span class="nx">out</span><span class="p">,</span> <span class="p">{</span> + <span class="nx">correlationId</span><span class="o">:</span> <span class="nx">msg</span><span class="p">.</span><span class="nx">properties</span><span class="p">.</span><span class="nx">correlationId</span> + <span class="p">});</span> + + <span class="c1">//Acknowledge the job done with the message.</span> + <span class="nx">ch</span><span class="p">.</span><span class="nx">ack</span><span class="p">(</span><span class="nx">msg</span><span class="p">);</span> + <span class="p">});</span> + <span class="p">});</span> + <span class="p">});</span> +<span class="p">});</span> +</pre></div> +<p>The key points here are. Open just one connection to the hole server. You CAN create one channel for every request that you receive, but it can take some time if you have a really big cluster of RabbitMQ. It was a quick tutorial, but I hope that it was able to clear a few questions that you might have when working with rabbit and express.</p> +Microservices with NodeJS, Express.js and RabbitMQ Part 12018-04-04T11:25:00-03:002018-04-04T11:25:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-04-04:/en/microservices_nodejs_express_rabbitmq_part_1.html<p>This is the first part of a microservices development series. The service will consist of the bellow architecture, where we will expose an image optimizer service that will forward the request to a <a class="reference external" href="https://www.rabbitmq.com/">RabbitMQ</a> queue and answer with the bytecode of the optimized image. It shouldn't be a long series …</p><p>This is the first part of a microservices development series. The service will consist of the bellow architecture, where we will expose an image optimizer service that will forward the request to a <a class="reference external" href="https://www.rabbitmq.com/">RabbitMQ</a> queue and answer with the bytecode of the optimized image. It shouldn't be a long series so let's see what we can do.</p> +<img alt="Service architecture" src="/images/microservices_rabit_pt1.png" /> +<p>Let's get our environment working. First, we'll need to install the libraries that we'll use.</p> +<p>Create a dir and initialize the nodejs application inside it (<cite>npm init</cite>) and then let's install the deps.</p> +<ul class="simple"> +<li>amqplib - AMQP lib to interact with rabbitmq</li> +<li>express - Do our basic rest API</li> +<li>express-fileupload - easy file upload parser</li> +<li>imagemin and imagemin-pngquant - our image compacter</li> +</ul> +<div class="highlight"><pre><span></span>npm install --save express amqplib express-fileupload imagemin imagemin-pngquant +</pre></div> +<p>Now let's write the entry points for our service, we'll have two basic entry points. The path <cite>/</cite> that will have a welcome message, the second path will be <cite>/upload</cite> and this is the one that will handle the image and produce a job for our workers.</p> +<div class="highlight"><pre><span></span><span class="kr">const</span> <span class="nx">express</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;express&#39;</span><span class="p">);</span> +<span class="kr">const</span> <span class="nx">fileUpload</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;express-fileupload&#39;</span><span class="p">);</span> + +<span class="c1">//Instantiate the app and set the fileupload parser to manage files</span> +<span class="kr">const</span> <span class="nx">app</span> <span class="o">=</span> <span class="nx">express</span><span class="p">();</span> +<span class="nx">app</span><span class="p">.</span><span class="nx">use</span><span class="p">(</span><span class="nx">fileUpload</span><span class="p">());</span> + +<span class="c1">//Our index entry point</span> +<span class="nx">app</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;/&#39;</span><span class="p">,</span> <span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="nx">res</span><span class="p">.</span><span class="nx">send</span><span class="p">(</span><span class="s1">&#39;Hello From ImageCompacter service&#39;</span><span class="p">));</span> + +<span class="c1">//The path that will handle the image file and throw them to the queue</span> +<span class="nx">app</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="s1">&#39;/upload&#39;</span><span class="p">,</span> <span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="c1">//With express-fileupload we can grab the files like this</span> + <span class="kd">let</span> <span class="nx">img</span> <span class="o">=</span> <span class="nx">req</span><span class="p">.</span><span class="nx">files</span><span class="p">.</span><span class="nx">image</span><span class="p">;</span> <span class="c1">//&quot;image&quot; is the name of the input</span> + + <span class="nx">res</span><span class="p">.</span><span class="nx">send</span><span class="p">(</span><span class="s1">&#39;Not ready yet&#39;</span><span class="p">);</span> +<span class="p">});</span> + +<span class="c1">//Finally start the app with the given port number</span> +<span class="nx">app</span><span class="p">.</span><span class="nx">listen</span><span class="p">(</span><span class="mi">4000</span><span class="p">,</span> <span class="p">()</span> <span class="p">=&gt;</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;Example app listening on port 4000!&#39;</span><span class="p">));</span> +</pre></div> +<p>Let's check if it works, run the service with node.</p> +<div class="highlight"><pre><span></span>node index.js +Example app listening on port <span class="m">4000</span>! +</pre></div> +<p>Open the browser and check if it prints our hello message when accessing <cite>localhost:4000</cite>. Works? Greate. Now let's work with the image and see how we do it. To optimize our image, we'll use the library imagemin and <a class="reference external" href="https://www.npmjs.com/package/imagemin-pngquant">imagemin-pngquant</a>, it will be that simple for now, we'll work with rabbitmq latter.</p> +<div class="highlight"><pre><span></span><span class="kr">const</span> <span class="nx">imagemin</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;imagemin&#39;</span><span class="p">);</span> +<span class="kr">const</span> <span class="nx">imageminPngquant</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;imagemin-pngquant&#39;</span><span class="p">);</span> +<span class="c1">//...</span> + +<span class="c1">//The path that will handle the image file and throw them to the queue</span> +<span class="nx">app</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="s1">&#39;/upload&#39;</span><span class="p">,</span> <span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="kd">let</span> <span class="nx">img</span> <span class="o">=</span> <span class="nx">req</span><span class="p">.</span><span class="nx">files</span><span class="p">.</span><span class="nx">image</span><span class="p">;</span> <span class="c1">//&quot;image&quot; is the name of the input</span> + + <span class="nx">imagemin</span><span class="p">.</span><span class="nx">buffer</span><span class="p">(</span><span class="nx">img</span><span class="p">.</span><span class="nx">data</span><span class="p">,</span> <span class="p">{</span> + <span class="nx">plugins</span><span class="o">:</span> <span class="p">[</span><span class="nx">imageminPngquant</span><span class="p">()]</span> + <span class="p">})</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">out</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="nx">res</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="nx">out</span><span class="p">,</span><span class="s1">&#39;binary&#39;</span><span class="p">);</span> + <span class="nx">res</span><span class="p">.</span><span class="nx">end</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="s1">&#39;binary&#39;</span><span class="p">);</span> + <span class="p">});</span> +<span class="p">});</span> + + <span class="c1">//...</span> +</pre></div> +<p>Use <a class="reference external" href="https://www.getpostman.com/">Postman</a> to test the request. To see if it will work, make a request to <cite>http://localhost:4000/upload</cite> with a formdata with a file. Select the &quot;send and Download&quot; instead of &quot;Send&quot; and you should have an image after that. Bellow an image of how your postman should be.</p> +<img alt="Postman" src="/images/microservice_postman.png" /> +<p>That's it for today, next week we'll change our code to use RabbitMQ.</p> +Connecting to a database through SSH2018-03-29T10:03:00-03:002018-03-29T10:03:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-03-29:/en/connecting_to_database_through_ssh.html<p>If someday, for some reason, you need to establish a connection with a database which is behind a firewall and you only have SSH access on that server (and you don't want to use a CLI) you can do an SSH tunnel. It's pretty simple, bellow has a sample of …</p><p>If someday, for some reason, you need to establish a connection with a database which is behind a firewall and you only have SSH access on that server (and you don't want to use a CLI) you can do an SSH tunnel. It's pretty simple, bellow has a sample of how to allow connections to a remote Firebird database.</p> +<div class="highlight"><pre><span></span>ssh -L <span class="m">3051</span>:192.168.1.9:3050 username@192.168.1.9 +</pre></div> +<p>The <cite>-L</cite> parameter tells to SSH do a local port forwarding on local port <cite>3051</cite> to remote port <cite>3050</cite>. You can use it to a connection with many services, not just databases.</p> +<p>You can do the reverse kind of tunnel, forward connections from the host to your local machine, you just have to change the parameter form &quot;-L&quot; to &quot;-R&quot; and the port order is inverted, first come the port where the server will listen and after your localhost port. This remote port forwarding must be enabled on the server. Look for <cite>GatewayPorts</cite> at the ssh config file.</p> +<div class="highlight"><pre><span></span>ssh -R <span class="m">3050</span>:localhost:3050 username@192.168.1.9 +</pre></div> +<p>Why whould you need something like that?? Let's say you want to share a localhost site/database with a friend, but your internet connection don't allow you to expose any port but you have access to a remote server witch can do that. Problem solved ;).</p> +Now posting on Grepora2018-03-24T00:40:00-03:002018-03-24T00:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-03-24:/en/now_posting_on_grepora.html<p>A few weeks ago I started posting at <a class="reference external" href="https://grepora.com/blog/">Grepora</a> blog. If you like or are looking for some Oracle related stuff, Grepora it's a good place to go and spend a time reading :). From time to time I'll be posting there, it doesn't mean that this blog will be closed …</p><p>A few weeks ago I started posting at <a class="reference external" href="https://grepora.com/blog/">Grepora</a> blog. If you like or are looking for some Oracle related stuff, Grepora it's a good place to go and spend a time reading :). From time to time I'll be posting there, it doesn't mean that this blog will be closed or anything like that, but probably this one will be more focused on Front-end stuff, a few tricks with linux and a lil less with Java.</p> +Scaffolding a React app with Parcel and Yeoman2018-03-17T13:00:00-03:002018-03-17T13:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-03-17:/en/scaffolding_react_app_with_parcel_yeoman.html<p>Since <a class="reference external" href="https://parceljs.org/">Parcel JS</a> arrived, I've been using it a lot as an awesome alternative for WebPack. Webpack isn't bad but IMO it's too complex for the job and parcel do the same (at least the basic) with almost zero configuration. But if you need to create many apps (like a …</p><p>Since <a class="reference external" href="https://parceljs.org/">Parcel JS</a> arrived, I've been using it a lot as an awesome alternative for WebPack. Webpack isn't bad but IMO it's too complex for the job and parcel do the same (at least the basic) with almost zero configuration. But if you need to create many apps (like a react app) over and over again, it get's a lil boring following the basic steps.</p> +<div class="highlight"><pre><span></span>npm init -y +npm install --save react +npm install --save react-dom +npm install --save-dev parcel-bundler +npm install --save-dev babel-preset-env +npm install --save-dev babel-preset-react + +<span class="c1">#create .babelrc file</span> +<span class="c1">#create html, css, jsx files</span> + +parcel index.html +</pre></div> +<p>It's not a hard job, a simple shell script do the job, but what if you need some IFs when creating the app, or even change a few things at the <cite>package.json</cite>? A shell script still does the job, but come on... There is a better way. <a class="reference external" href="http://yeoman.io/">Yeoman</a> is here for you. I've already <a class="reference external" href="https://www.sipmann.com/en/desenvolvendo-app-firefoxos-pt.html">talked about it</a> on another post (Portuguese post).</p> +<p>Straight to the point, I've released a Yeoman generator to get the things a lil quicker. The name is <a class="reference external" href="https://www.npmjs.com/package/generator-parcel-react">generator-parcel-react</a> and it still lacks a few things that I will deal with soon. It's pretty simple to use it.</p> +<div class="highlight"><pre><span></span><span class="c1">#First time only</span> +npm install -g yo +npm install -g generator-parcel-react + +<span class="c1">#every time you create a new app</span> +yo parcel-react +</pre></div> +<p>And that's it. Right now you can scaffold and app with React, SASS and React Router. Hope you like it and feel free to ask new features.</p> +Could not open connection with MySQL and Hibernate2018-03-09T12:35:00-03:002018-03-09T12:35:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-03-09:/en/cloud-not-open-connection-java-mysql-hibernate.html<p>Last day I decided to deploy a MySQL Docker image to work with my Java application. I've been using PostgreSQL instead and have no problems at all, but after I moved to MySQL, the app didn't connect anymore with the database and throw some &quot;Could not open connection&quot; at my …</p><p>Last day I decided to deploy a MySQL Docker image to work with my Java application. I've been using PostgreSQL instead and have no problems at all, but after I moved to MySQL, the app didn't connect anymore with the database and throw some &quot;Could not open connection&quot; at my face, but why? I've tried to connect to it manually and got the same problem.</p> +<p>After some research, I found that the true error should be java.sql.SQLException: null, message from server: &quot;Host '172.17.0.4' is not allowed to connect to this MySQL server&quot; but it wasn't showing to me...</p> +<p>After all, be aware that with the docker image MySQL:5.7.21 (latest version right now) the root user isn't allowed to remote connect to the database (it's alright, security reasons) and if you still want to do remote connections to it with root there are a few things you can do.</p> +<ol class="arabic simple"> +<li>Create a user or allow root to access from other IPs.</li> +</ol> +<div class="highlight"><pre><span></span><span class="o">#</span><span class="k">No</span> <span class="k">access</span> <span class="k">to</span> <span class="k">user</span> <span class="n">root</span> <span class="k">on</span> <span class="k">any</span> <span class="n">other</span> <span class="n">IP</span> +<span class="k">SELECT</span> <span class="k">User</span><span class="p">,</span> <span class="k">Host</span> <span class="k">FROM</span> <span class="n">mysql</span><span class="p">.</span><span class="k">user</span><span class="p">;</span> +<span class="o">+</span><span class="c1">---------------+-----------+</span> +<span class="o">|</span> <span class="k">User</span> <span class="o">|</span> <span class="k">Host</span> <span class="o">|</span> +<span class="o">+</span><span class="c1">---------------+-----------+</span> +<span class="o">|</span> <span class="n">healthchecker</span> <span class="o">|</span> <span class="n">localhost</span> <span class="o">|</span> +<span class="o">|</span> <span class="n">root</span> <span class="o">|</span> <span class="n">localhost</span> <span class="o">|</span> +<span class="o">+</span><span class="c1">---------------+-----------+</span> +<span class="mi">2</span> <span class="k">rows</span> <span class="k">in</span> <span class="k">set</span> <span class="p">(</span><span class="mi">0</span><span class="p">.</span><span class="mi">01</span> <span class="n">sec</span><span class="p">)</span> + +<span class="k">CREATE</span> <span class="k">USER</span> <span class="s1">&#39;newuser&#39;</span><span class="o">@</span><span class="s1">&#39;%&#39;</span> <span class="n">IDENTIFIED</span> <span class="k">BY</span> <span class="s1">&#39;password&#39;</span><span class="p">;</span> <span class="o">#%</span> <span class="n">mean</span> <span class="k">any</span> <span class="n">IP</span> +<span class="k">GRANT</span> <span class="k">ALL</span> <span class="k">PRIVILEGES</span> <span class="k">ON</span> <span class="o">*</span><span class="p">.</span><span class="o">*</span> <span class="k">TO</span> <span class="s1">&#39;newuser&#39;</span><span class="o">@</span><span class="s1">&#39;%&#39;</span><span class="p">;</span> <span class="o">#*</span><span class="p">.</span><span class="o">*</span> <span class="n">mean</span> <span class="k">database</span><span class="p">.</span><span class="k">table</span> <span class="p">;)</span> +</pre></div> +<ol class="arabic simple" start="2"> +<li>Use MariaDB instead, witch come (at least on the version 10.2.13) with root allowed to do remote connections and will work like MySQL :)</li> +</ol> +<p>I changed to <a class="reference external" href="https://mariadb.org/">MariaDB</a> as it work without creating user or any changes on the Java code or the <cite>docker run command</cite>.</p> +Solving java.net.SocketException: Protocol family unavailable on a Java + Docker + WildFly2018-03-04T17:40:00-03:002018-03-04T17:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-03-04:/en/socketException-protocol-family-unavailable-java-docker-wildfly.html<p>On the last days I've been playing with <a class="reference external" href="http://wildfly-swarm.io/">WildFly Swarm</a> and I decided to deploy a simple app with Docker. Should work fine, at least that was what I thought. Built a container with the following Dockerfile and instead of a working web app, all that I got was the …</p><p>On the last days I've been playing with <a class="reference external" href="http://wildfly-swarm.io/">WildFly Swarm</a> and I decided to deploy a simple app with Docker. Should work fine, at least that was what I thought. Built a container with the following Dockerfile and instead of a working web app, all that I got was the error <cite>java.net.SocketException: Protocol family unavailable</cite>.</p> +<div class="highlight"><pre><span></span><span class="k">FROM</span> <span class="s">java:openjdk-8-jdk</span> + +<span class="k">COPY</span> target/issues.jar /opt/issues.jar + +<span class="k">EXPOSE</span><span class="s"> 8080</span> + +<span class="k">CMD</span> <span class="p">[</span><span class="s2">&quot;java&quot;</span><span class="p">,</span><span class="s2">&quot;-jar&quot;</span><span class="p">,</span><span class="s2">&quot;/opt/issues.jar&quot;</span><span class="p">]</span> +</pre></div> +<p>For some reason, WildFly and Java decided to use the IPv6 network interface from Docker instead the v4, so all you have to do is tell Java to prefer IPv4 instead with the following configuration option in your pom.xml file inside your WildFly plugin.</p> +<div class="highlight"><pre><span></span><span class="nt">&lt;plugin&gt;</span> + <span class="nt">&lt;groupId&gt;</span>org.wildfly.swarm<span class="nt">&lt;/groupId&gt;</span> + <span class="nt">&lt;artifactId&gt;</span>wildfly-swarm-plugin<span class="nt">&lt;/artifactId&gt;</span> + <span class="nt">&lt;version&gt;</span>2018.2.0<span class="nt">&lt;/version&gt;</span> + + <span class="c">&lt;!-- ADD THIS --&gt;</span> + <span class="nt">&lt;configuration&gt;</span> + <span class="nt">&lt;mainClass&gt;</span>org.wildfly.swarm.examples.netflix.ribbon.frontend.Main<span class="nt">&lt;/mainClass&gt;</span> + <span class="nt">&lt;properties&gt;</span> + <span class="nt">&lt;java.net.preferIPv4Stack&gt;</span>true<span class="nt">&lt;/java.net.preferIPv4Stack&gt;</span> + <span class="nt">&lt;/properties&gt;</span> + <span class="nt">&lt;/configuration&gt;</span> +</pre></div> +<p>Another way to solve is adding the same properties to the run command at the Dockerfile, so you choose where you'll add it. Bellow the Dockerfile solution.</p> +<div class="highlight"><pre><span></span><span class="k">FROM</span> <span class="s">java:openjdk-8-jdk</span> +<span class="k">ENV</span> <span class="nv">JAVA_OPTS</span><span class="o">=</span><span class="s2">&quot;-Djava.net.preferIPv4Stack=true -Djava.net.preferIPv4Addresses=true&quot;</span> + +<span class="k">COPY</span> target/issues.jar /opt/issues.jar + +<span class="k">EXPOSE</span><span class="s"> 8080</span> + +<span class="k">ENTRYPOINT</span> <span class="nb">exec</span> java <span class="nv">$JAVA_OPTS</span> -jar /opt/issues.jar +</pre></div> +Change display settings on linux with Disper2018-02-27T12:40:00-03:002018-02-27T12:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-02-27:/en/linux-external-display-with-disper.html<p>From time to time, I change the Linux distro on my laptop or just do a fresh install on it. And once in a while, have random problems with external displays. It can be something really &quot;simple&quot; like don't detecting the external monitor or something crazy like the image below …</p><p>From time to time, I change the Linux distro on my laptop or just do a fresh install on it. And once in a while, have random problems with external displays. It can be something really &quot;simple&quot; like don't detecting the external monitor or something crazy like the image below.</p> +<img alt="Display bug" src="/images/bug.png" /> +<p>As you can see at the image, the mint detected the display but mirrored it in a crazy way that works but doesn't at the same time. If you try anything and doesn't get working, or just wanna skip the whole job of configuring complexes text files, give a try to <a class="reference external" href="http://willem.engen.nl/projects/disper/">Disper</a>. Download the latest version. +Extract it on any folder, and make install it (on the extracted folder).</p> +<div class="highlight"><pre><span></span>make install +</pre></div> +<p>After that, you can start using it... There are a few options that will serve you well.</p> +<div class="highlight"><pre><span></span>disper -e <span class="c1">#extend your display</span> +</pre></div> +<div class="highlight"><pre><span></span>disper -c <span class="c1">#clone your display</span> +</pre></div> +<div class="highlight"><pre><span></span>disper -s <span class="c1">#only your external display</span> +</pre></div> +Java - Files.readAllBytes throws OutOfMemory2018-02-17T13:00:00-02:002018-02-17T13:00:00-02:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-02-17:/en/reading-files-java-readAllBytes-outofmemory.html<p>When you need to interact with files, there's the possibility to read all bytes from the file with <cite>Files.readAllBytes</cite>. But be aware of the kinds of files your application will deal with because the Java API files have a limit for the buffer that is defined as <cite>Integer.MAX_VALUE …</cite></p><p>When you need to interact with files, there's the possibility to read all bytes from the file with <cite>Files.readAllBytes</cite>. But be aware of the kinds of files your application will deal with because the Java API files have a limit for the buffer that is defined as <cite>Integer.MAX_VALUE</cite> as you can see above or at the OpenJDK sources.</p> +<div class="highlight"><pre><span></span><span class="kd">public</span> <span class="kd">static</span> <span class="kt">byte</span><span class="o">[]</span> <span class="nf">readAllBytes</span><span class="p">(</span><span class="n">Path</span> <span class="n">path</span><span class="p">)</span> <span class="kd">throws</span> <span class="n">IOException</span> <span class="p">{</span> + <span class="k">try</span> <span class="p">(</span><span class="n">FileChannel</span> <span class="n">fc</span> <span class="o">=</span> <span class="n">FileChannel</span><span class="p">.</span><span class="na">open</span><span class="p">(</span><span class="n">path</span><span class="p">))</span> <span class="p">{</span> + <span class="kt">long</span> <span class="n">size</span> <span class="o">=</span> <span class="n">fc</span><span class="p">.</span><span class="na">size</span><span class="p">();</span> + <span class="k">if</span> <span class="p">(</span><span class="n">size</span> <span class="o">&gt;</span> <span class="p">(</span><span class="kt">long</span><span class="p">)</span><span class="n">Integer</span><span class="p">.</span><span class="na">MAX_VALUE</span><span class="p">)</span> + <span class="k">throw</span> <span class="k">new</span> <span class="n">OutOfMemoryError</span><span class="p">(</span><span class="s">&quot;Required array size too large&quot;</span><span class="p">);</span> + + <span class="kt">byte</span><span class="o">[]</span> <span class="n">arr</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">byte</span><span class="o">[</span><span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">size</span><span class="o">]</span><span class="p">;</span> + <span class="n">ByteBuffer</span> <span class="n">bb</span> <span class="o">=</span> <span class="n">ByteBuffer</span><span class="p">.</span><span class="na">wrap</span><span class="p">(</span><span class="n">arr</span><span class="p">);</span> + <span class="k">while</span> <span class="p">(</span><span class="n">bb</span><span class="p">.</span><span class="na">hasRemaining</span><span class="p">())</span> <span class="p">{</span> + <span class="k">if</span> <span class="p">(</span><span class="n">fc</span><span class="p">.</span><span class="na">read</span><span class="p">(</span><span class="n">bb</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> + <span class="c1">// truncated</span> + <span class="k">break</span><span class="p">;</span> + <span class="p">}</span> + <span class="p">}</span> + + <span class="kt">int</span> <span class="n">nread</span> <span class="o">=</span> <span class="n">bb</span><span class="p">.</span><span class="na">position</span><span class="p">();</span> + <span class="k">return</span> <span class="p">(</span><span class="n">nread</span> <span class="o">==</span> <span class="n">size</span><span class="p">)</span> <span class="o">?</span> <span class="n">arr</span> <span class="p">:</span> <span class="n">Arrays</span><span class="p">.</span><span class="na">copyOf</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="n">nread</span><span class="p">);</span> + <span class="p">}</span> +<span class="p">}</span> +</pre></div> +<p>With that in mind, check if isn't better read chunks of bytes e work with that slice in exchange of loading the whole file into the memory ;). Above a simple example of how you can read chunks of bytes from the file.</p> +<div class="highlight"><pre><span></span><span class="kt">byte</span><span class="o">[]</span> <span class="n">buffer</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">byte</span><span class="o">[</span><span class="mi">1024</span><span class="o">]</span><span class="p">;</span> +<span class="n">FileInputStream</span> <span class="n">in</span> <span class="o">=</span> <span class="k">new</span> <span class="n">FileInputStream</span><span class="p">(</span><span class="n">file</span><span class="p">);</span> +<span class="kt">int</span> <span class="n">rc</span> <span class="o">=</span> <span class="n">in</span><span class="p">.</span><span class="na">read</span><span class="p">(</span><span class="n">buffer</span><span class="p">);</span> +<span class="k">while</span> <span class="p">(</span><span class="n">rc</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span> +<span class="p">{</span> + <span class="c1">//crazy stuff here with buffer</span> + <span class="n">rc</span> <span class="o">=</span> <span class="n">in</span><span class="p">.</span><span class="na">read</span><span class="p">(</span><span class="n">buffer</span><span class="p">);</span> +<span class="p">}</span> +</pre></div> + \ No newline at end of file diff --git a/en/feeds/all-en.atom.xml.gz b/en/feeds/all-en.atom.xml.gz new file mode 100644 index 000000000..7ccfb0e80 Binary files /dev/null and b/en/feeds/all-en.atom.xml.gz differ diff --git a/en/feeds/all.atom.xml b/en/feeds/all.atom.xml new file mode 100644 index 000000000..0725d79ab --- /dev/null +++ b/en/feeds/all.atom.xml @@ -0,0 +1,1270 @@ + +Sipmannhttps://www.sipmann.com/en/2020-12-21T13:30:00-03:00Monitoring MySQL restarts with PowerShell2020-12-21T13:30:00-03:002020-12-21T13:30:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-12-21:/en/monitoring-mysql-restarts-with-powershell.html<p>Hey folks, it's time for another PowerShell script. If you haven't seen the other ones, check the links below.</p> +<ul> +<li><a href="https://www.sipmann.com/en/monitoring-mysql-replication-with-powershell.html">Monitoring MySQL replication with PowerShell</a></li> +</ul> +<p>Well, this one it's a pretty simple script, but again, if your customer doesn't have a Zabbix server or doesn't allow you to setup one to …</p><p>Hey folks, it's time for another PowerShell script. If you haven't seen the other ones, check the links below.</p> +<ul> +<li><a href="https://www.sipmann.com/en/monitoring-mysql-replication-with-powershell.html">Monitoring MySQL replication with PowerShell</a></li> +</ul> +<p>Well, this one it's a pretty simple script, but again, if your customer doesn't have a Zabbix server or doesn't allow you to setup one to do the monitoring, a set of scripts can be handy. We start executing some basic query <code>SHOW GLOBAL STATUS LIKE 'Uptime'</code>, with that we'll get exactly what we're looking for.</p> +<p>If for some reason, the command fails (watch for the "global" variable called <code>$lastExitCode</code>), we send an e-mail telling you about that connection problem.</p> +<p>And then, we get to the part where we parse the value, this one is pretty similar to the parse we did on the first post about using PowerShell to monitor MySQL. But we basically look for the Value line, split it by space and then parse the second position to an integer. And then all we have to do is check if the uptime is lower than our threshold, if it is we send an e-mail.</p> +<div class="highlight"><pre><span></span><code><span class="nv">$MailFrom</span> <span class="p">=</span> <span class="s1">&#39;maurio[at]sipmann.com&#39;</span> +<span class="nv">$MailTo</span> <span class="p">=</span> <span class="s1">&#39;mauricio[at]sipmann.com&#39;</span> +<span class="nv">$MysqlHost</span> <span class="p">=</span> <span class="s1">&#39;127.0.0.1&#39;</span> +<span class="nv">$MysqlUser</span> <span class="p">=</span> <span class="s1">&#39;root&#39;</span> +<span class="nv">$MysqlPass</span> <span class="p">=</span> <span class="s1">&#39;123&#39;</span> + + +<span class="nv">$data</span> <span class="p">=</span> <span class="p">$(</span><span class="n">mysql</span> <span class="n">-h</span> <span class="nv">$MysqlHost</span> <span class="n">-u</span> <span class="nv">$MysqlUser</span> <span class="n">-p</span><span class="s2">&quot;$MysqlPass&quot;</span> <span class="n">-e</span> <span class="s2">&quot;SHOW GLOBAL STATUS LIKE &#39;Uptime&#39; \G&quot;</span><span class="p">)</span> + +<span class="cm">&lt;# Unable to execute the sql Command #&gt;</span> +<span class="k">if</span> <span class="p">(</span><span class="nv">$lastExitCode</span> <span class="o">-eq</span> <span class="n">1</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Send-MailMessage</span> <span class="n">-To</span> <span class="nv">$MailTo</span> <span class="n">-From</span> <span class="nv">$MailFrom</span> <span class="n">-Subject</span> <span class="s1">&#39;Connection problem&#39;</span> <span class="n">-bodyAsHtml</span> <span class="s2">&quot;Connection problem on host ${MysqlHost}&quot;</span> <span class="n">-Credential</span> <span class="nb">Get-Credential</span> <span class="n">-SmtpServer</span> <span class="s1">&#39;smtp.office365.com&#39;</span> <span class="n">-Port</span> <span class="n">587</span> <span class="n">-UseSsl</span> + <span class="n">exit</span> +<span class="p">}</span> + +<span class="nv">$UpTime</span> <span class="p">=</span> <span class="no">[int]</span><span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Value:&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> + +<span class="cm">&lt;# If the uptime is lower then 20 minutes #&gt;</span> +<span class="k">if</span> <span class="p">(</span><span class="nv">$UpTime</span> <span class="o">-lt</span> <span class="n">1200</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Send-MailMessage</span> <span class="n">-To</span> <span class="nv">$MailTo</span> <span class="n">-From</span> <span class="nv">$MailFrom</span> <span class="n">-Subject</span> <span class="s2">&quot;MySQL Restarted&quot;</span> <span class="n">-bodyAsHtml</span> <span class="s2">&quot;MySQL host ${MysqlHost} restarted less than 20 minutes ago&quot;</span> <span class="n">-Credential</span> <span class="nb">Get-Credential</span> <span class="n">-SmtpServer</span> <span class="s1">&#39;smtp.office365.com&#39;</span> <span class="n">-Port</span> <span class="n">587</span> <span class="n">-UseSsl</span> +<span class="p">}</span> +</code></pre></div> + +<p>This script (and the other ones I use) is available at my GitHub <a href="https://github.com/sipmann/PowerShellScripts">here</a>. Keep in mind that the ones on the GitHub repo, are a little different from here.</p>Monitorando restarts do MySQL com PowerShell2020-12-21T13:30:00-03:002020-12-21T13:30:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-12-21:/pt/monitoring-mysql-restarts-with-powershell.html<p>Bom, chegou a hora para mais um script PowerShell. Se você ainda não viu os outros, de uma olhada no link abaixo.</p> +<ul> +<li><a href="https://www.sipmann.com/pt/monitoring-mysql-replication-with-powershell.html">Monitorando status de replicação do MySQL com PowerShell</a></li> +</ul> +<p>Este aqui é um script bem simples, mas novamente, se seu cliente não possui um servidor Zabbix ou não permite …</p><p>Bom, chegou a hora para mais um script PowerShell. Se você ainda não viu os outros, de uma olhada no link abaixo.</p> +<ul> +<li><a href="https://www.sipmann.com/pt/monitoring-mysql-replication-with-powershell.html">Monitorando status de replicação do MySQL com PowerShell</a></li> +</ul> +<p>Este aqui é um script bem simples, mas novamente, se seu cliente não possui um servidor Zabbix ou não permite que você configure um para realizar este monitoramento, um conjunto de scripts pode ser bem útil. Primeiramente nós executamos uma query báscia <code>SHOW GLOBAL STATUS LIKE 'Uptime'</code>, com ela nós conseguimos capturar exatamente o que nós estamos procurando.</p> +<p>Se por alguma razão o comando falhar (verificamos atravez da variábel global <code>$lastExitCode</code>), nós mandamos um e-mail lhe avisando sobre o problema ocorrido.</p> +<p>E então, nós chegamos à parte onde fazemos o parse do valor obtido, esta parte é bem similar ao parse que codificamos no primeiro post sobre monitoramento utilizando PowerShell. Nós basicamentes procuramos pela linha contendo <code>Value</code>, separamos por espaço e então parseamos a segunda posição em um inteiro. Então tudo que precisamos fazer é verificar se o valor parseado é menor que o nosso threshold, se for menor, nós mandamos um e-mail.</p> +<div class="highlight"><pre><span></span><code><span class="nv">$MailFrom</span> <span class="p">=</span> <span class="s1">&#39;maurio[at]sipmann.com&#39;</span> +<span class="nv">$MailTo</span> <span class="p">=</span> <span class="s1">&#39;mauricio[at]sipmann.com&#39;</span> +<span class="nv">$MysqlHost</span> <span class="p">=</span> <span class="s1">&#39;127.0.0.1&#39;</span> +<span class="nv">$MysqlUser</span> <span class="p">=</span> <span class="s1">&#39;root&#39;</span> +<span class="nv">$MysqlPass</span> <span class="p">=</span> <span class="s1">&#39;123&#39;</span> + + +<span class="nv">$data</span> <span class="p">=</span> <span class="p">$(</span><span class="n">mysql</span> <span class="n">-h</span> <span class="nv">$MysqlHost</span> <span class="n">-u</span> <span class="nv">$MysqlUser</span> <span class="n">-p</span><span class="s2">&quot;$MysqlPass&quot;</span> <span class="n">-e</span> <span class="s2">&quot;SHOW GLOBAL STATUS LIKE &#39;Uptime&#39; \G&quot;</span><span class="p">)</span> + +<span class="cm">&lt;# Unable to execute the sql Command #&gt;</span> +<span class="k">if</span> <span class="p">(</span><span class="nv">$lastExitCode</span> <span class="o">-eq</span> <span class="n">1</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Send-MailMessage</span> <span class="n">-To</span> <span class="nv">$MailTo</span> <span class="n">-From</span> <span class="nv">$MailFrom</span> <span class="n">-Subject</span> <span class="s1">&#39;Connection problem&#39;</span> <span class="n">-bodyAsHtml</span> <span class="s2">&quot;Connection problem on host ${MysqlHost}&quot;</span> <span class="n">-Credential</span> <span class="nb">Get-Credential</span> <span class="n">-SmtpServer</span> <span class="s1">&#39;smtp.office365.com&#39;</span> <span class="n">-Port</span> <span class="n">587</span> <span class="n">-UseSsl</span> + <span class="n">exit</span> +<span class="p">}</span> + +<span class="nv">$UpTime</span> <span class="p">=</span> <span class="no">[int]</span><span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Value:&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> + +<span class="cm">&lt;# If the uptime is lower then 20 minutes #&gt;</span> +<span class="k">if</span> <span class="p">(</span><span class="nv">$UpTime</span> <span class="o">-lt</span> <span class="n">1200</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Send-MailMessage</span> <span class="n">-To</span> <span class="nv">$MailTo</span> <span class="n">-From</span> <span class="nv">$MailFrom</span> <span class="n">-Subject</span> <span class="s2">&quot;MySQL Restarted&quot;</span> <span class="n">-bodyAsHtml</span> <span class="s2">&quot;MySQL host ${MysqlHost} restarted less than 20 minutes ago&quot;</span> <span class="n">-Credential</span> <span class="nb">Get-Credential</span> <span class="n">-SmtpServer</span> <span class="s1">&#39;smtp.office365.com&#39;</span> <span class="n">-Port</span> <span class="n">587</span> <span class="n">-UseSsl</span> +<span class="p">}</span> +</code></pre></div> + +<p>Este script (e os outros que eu utilizo) estão disponíveis no meu GitHub <a href="https://github.com/sipmann/PowerShellScripts">aqui</a>. Tenha em mente que os scripts localizados no GitHub, são um pouco diferentes do que exibido aqui. Espero que tenha achado útil.</p>Changing a MySQL user password across multiple application instances without downtime2020-12-09T13:40:00-03:002020-12-09T13:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-12-09:/en/mysql-dual-password-functionality.html<p>Do you need to change the password of a MySQL user that it's being used in an application, and can't allow a single downtime? Well, MySQL 8.0.14 came with a feature called <a href="https://dev.mysql.com/doc/refman/8.0/en/password-management.html#dual-passwords">Dual Password Support</a>, with it you can change the password keeping the previous password as a …</p><p>Do you need to change the password of a MySQL user that it's being used in an application, and can't allow a single downtime? Well, MySQL 8.0.14 came with a feature called <a href="https://dev.mysql.com/doc/refman/8.0/en/password-management.html#dual-passwords">Dual Password Support</a>, with it you can change the password keeping the previous password as a kind of backup. That way you still can log in using the old password or can start using the new one. With that, the password change workflow it's the following.</p> +<p>1) Change password keeping the old one;</p> +<p>2) Deploy the new config to your app/cluster;</p> +<p>3) Discard the old password.</p> +<p>To change the password and keep the old one, you have the following command.</p> +<div class="highlight"><pre><span></span><code><span class="k">ALTER</span> <span class="n">USER</span> <span class="s1">&#39;appuser&#39;</span><span class="o">@</span><span class="s1">&#39;localhost&#39;</span> <span class="n">IDENTIFIED</span> <span class="k">BY</span> <span class="s1">&#39;new_password&#39;</span> <span class="n">RETAIN</span> <span class="n">CURRENT</span> <span class="n">PASSWORD</span><span class="p">;</span> +</code></pre></div> + +<p>To discard the old one, run the following.</p> +<div class="highlight"><pre><span></span><code><span class="k">ALTER</span> <span class="n">USER</span> <span class="s1">&#39;appuser&#39;</span><span class="o">@</span><span class="s1">&#39;localhost&#39;</span> <span class="n">DISCARD</span> <span class="n">OLD</span> <span class="n">PASSWORD</span><span class="p">;</span> +</code></pre></div> + +<p>And you are done. Hope you find it as useful as I :)</p>Trocando a senha de um usuário do MySQL sem downtime da aplicação2020-12-09T13:40:00-03:002020-12-09T13:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-12-09:/pt/mysql-dual-password-functionality.html<p>Você deseja trocar a senha de um usuário do MySQL que está sendo utilizado por uma aplicação e não sofrer nenhum downtime? Bom, a versão 8.0.14 do MySQL foi liberada com uma feature chamada <a href="https://dev.mysql.com/doc/refman/8.0/en/password-management.html#dual-passwords">Dual Password Support</a>, com esta feature você pode alterar a senha de um usuário …</p><p>Você deseja trocar a senha de um usuário do MySQL que está sendo utilizado por uma aplicação e não sofrer nenhum downtime? Bom, a versão 8.0.14 do MySQL foi liberada com uma feature chamada <a href="https://dev.mysql.com/doc/refman/8.0/en/password-management.html#dual-passwords">Dual Password Support</a>, com esta feature você pode alterar a senha de um usuário mantendo a anterior ainda funcionando como uma forma de "backup". Desta forma, você ainda conseguirá autenticar com o usuário utilizando tanto a nova senha, quanto a anterior. Com isto, o seu processo de troca de senha fica algo como:</p> +<p>1) Troque a senha mantendo a anterior;</p> +<p>2) Faça o Deploy da nova configuração na sua aplicação/cluster;</p> +<p>3) Descarte a senha anterior.</p> +<p>Para alterar a senha mantendo a anterior, você deve rodar o seguinte comando:</p> +<div class="highlight"><pre><span></span><code><span class="k">ALTER</span> <span class="n">USER</span> <span class="s1">&#39;appuser&#39;</span><span class="o">@</span><span class="s1">&#39;localhost&#39;</span> <span class="n">IDENTIFIED</span> <span class="k">BY</span> <span class="s1">&#39;new_password&#39;</span> <span class="n">RETAIN</span> <span class="n">CURRENT</span> <span class="n">PASSWORD</span><span class="p">;</span> +</code></pre></div> + +<p>Para descartar a senha antiga, rode o seguinte:</p> +<div class="highlight"><pre><span></span><code><span class="k">ALTER</span> <span class="n">USER</span> <span class="s1">&#39;appuser&#39;</span><span class="o">@</span><span class="s1">&#39;localhost&#39;</span> <span class="n">DISCARD</span> <span class="n">OLD</span> <span class="n">PASSWORD</span><span class="p">;</span> +</code></pre></div> + +<p>E pronto. Espero que isto lhe ajude a evitar downtimes e dores de cabeça :)</p>Apache Nifi JSON to SQL Replacing underscore2020-12-02T14:00:00-03:002020-12-02T14:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-12-02:/en/apache-nifi-json-to-sql-replacing-underscore.html<p>Recently I was doing some ETL with Apache NiFi. But after a few minutes of drawing my flow, I saw that the component ConvertJSONToSQL was replacing the underscore ('_') from the field name in the where condition (I was preparing an Update SQL). That was weird because, at the set …</p><p>Recently I was doing some ETL with Apache NiFi. But after a few minutes of drawing my flow, I saw that the component ConvertJSONToSQL was replacing the underscore ('_') from the field name in the where condition (I was preparing an Update SQL). That was weird because, at the set statement, the field name was kept intact. After some research, I found that the property (see bellow) <code>Translate Field Names</code> was responsible for that weird replacement.</p> +<p><img alt="Apache NiFi JSONToSQL config" src="/images/apache_nifi_jsontosql.png"></p> +<p>Before setting it to <strong>FALSE</strong>, be aware that the properties on your JSON data must match exactly the name of your fields.</p>Apache Nifi JSON to SQL removendo underline2020-12-02T14:00:00-03:002020-12-02T14:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-12-02:/pt/apache-nifi-json-to-sql-replacing-underscore.html<p>Recentemente eu estava desenvolvendo alguns processos de ETL com o Apache NiFi. Mas após alguns minutos desenhando o meu fluxo, eu vi um comportamento estranho do componente ConvertJSONToSQL, que estava substituindo os underline ('_') do nome de um campo utilizado na condição da SQL (eu estava preparando um UPDATE). Aquilo …</p><p>Recentemente eu estava desenvolvendo alguns processos de ETL com o Apache NiFi. Mas após alguns minutos desenhando o meu fluxo, eu vi um comportamento estranho do componente ConvertJSONToSQL, que estava substituindo os underline ('_') do nome de um campo utilizado na condição da SQL (eu estava preparando um UPDATE). Aquilo estava estranho, uma vez que na definição do SET da SQL, o nome do campo permanecia inalterado. Depois de algumas pesquisas, achei uma doc que a propriedade (veja abaixo) <code>Translate Field Names</code> era a responsável por este comportamento estranho.</p> +<p><img alt="Apache NiFi JSONToSQL config" src="/images/apache_nifi_jsontosql.png"></p> +<p>Antes de definir a propriedade como <strong>FALSE</strong>, esteja ciente que as propriedades do seu JSON devem ser exatamente iguais aos nomes dos campos da sua tabela.</p>Blocking a user on SQL Server based on a schedule2020-11-14T07:00:00-03:002020-11-14T07:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-11-14:/en/blocking-user-on-sql-server-based-on-schedule.html<p>Ok, some time ago, I've posted about how you can set limits to connections on SQL Server using the <a href="https://www.sipmann.com/limiting-connection-resources-sql-server.html#.X6Cz8IhKhPY">Resource Governor</a>. But what if you can't use it? You always can block logins using a login trigger, but I don't like the idea of having selects running on every login …</p><p>Ok, some time ago, I've posted about how you can set limits to connections on SQL Server using the <a href="https://www.sipmann.com/limiting-connection-resources-sql-server.html#.X6Cz8IhKhPY">Resource Governor</a>. But what if you can't use it? You always can block logins using a login trigger, but I don't like the idea of having selects running on every login. So I came across with a solution using a stored procedure, a table and the Agent.</p> +<p>The main idea is, store the time that a user must be blocked and using the Agent, disable or enable the user. Bellow you can see the table (the table is in Portuguese, but I have a few comment blocks to help you).</p> +<div class="highlight"><pre><span></span><code><span class="k">CREATE</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"> </span><span class="p">(</span><span class="w"></span> +<span class="w"> </span><span class="n">Id</span><span class="w"> </span><span class="nc">INT</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">LoginName</span><span class="w"> </span><span class="nc">NVARCHAR</span><span class="p">(</span><span class="mi">100</span><span class="p">)</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">HrInicio</span><span class="w"> </span><span class="nc">TIME</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"> </span><span class="cm">/* Startint block time */</span><span class="w"></span> +<span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="nc">TIME</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"> </span><span class="cm">/* Ending block time */</span><span class="w"></span> +<span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="nc">INT</span><span class="w"> </span><span class="k">DEFAULT</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="cm">/* 0 = unblocked, 1 = blocked */</span><span class="w"></span> +<span class="w"> </span><span class="k">PRIMARY</span><span class="w"> </span><span class="k">KEY</span><span class="w"> </span><span class="p">(</span><span class="n">Id</span><span class="p">)</span><span class="w"></span> +<span class="p">);</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> + +<span class="cm">/* Don&#39;t block the SA user, precautions, you know */</span><span class="w"></span> +<span class="k">ALTER</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"></span> +<span class="w"> </span><span class="k">ADD</span><span class="w"> </span><span class="k">CONSTRAINT</span><span class="w"> </span><span class="n">chk_users</span><span class="w"> </span><span class="k">CHECK</span><span class="w"> </span><span class="p">(</span><span class="n">LoginName</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;sa&#39;</span><span class="p">));</span><span class="w"></span> + +<span class="k">ALTER</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"></span> +<span class="w"> </span><span class="k">ADD</span><span class="w"> </span><span class="k">CONSTRAINT</span><span class="w"> </span><span class="n">chk_hora_final_maior</span><span class="w"> </span><span class="k">CHECK</span><span class="w"> </span><span class="p">(</span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="n">HrInicio</span><span class="p">);</span><span class="w"></span> + +<span class="k">ALTER</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"></span> +<span class="w"> </span><span class="k">ADD</span><span class="w"> </span><span class="k">CONSTRAINT</span><span class="w"> </span><span class="n">chk_status_bloqueio</span><span class="w"> </span><span class="k">CHECK</span><span class="w"> </span><span class="p">(</span><span class="n">Bloqueado</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">));</span><span class="w"></span> + +<span class="k">CREATE</span><span class="w"> </span><span class="k">SEQUENCE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">seq_HorariosBloqueio</span><span class="w"> </span><span class="k">START</span><span class="w"> </span><span class="k">WITH</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="n">INCREMENT</span><span class="w"> </span><span class="k">BY</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +</code></pre></div> + +<p>After creating the table, let's check the procedure that will handle the enabling/disabling the users. Be aware that on the procedure, I've set the database name where the table was stored, you can change it replacing the <code>DBATOOLS</code> text to the database name where you created the table.</p> +<div class="highlight"><pre><span></span><code><span class="k">IF</span><span class="w"> </span><span class="nf">OBJECT_ID</span><span class="p">(</span><span class="s1">&#39;dbo.sp_ValidarLogin&#39;</span><span class="p">)</span><span class="w"> </span><span class="k">IS</span><span class="w"> </span><span class="k">NULL</span><span class="w"></span> +<span class="w"> </span><span class="k">EXEC</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;CREATE PROCEDURE dbo.sp_ValidarLogin AS RETURN 0;&#39;</span><span class="p">);</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> + +<span class="k">CREATE</span><span class="w"> </span><span class="ow">OR</span><span class="w"> </span><span class="k">ALTER</span><span class="w"> </span><span class="k">PROC</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">sp_ValidarLogin</span><span class="w"></span> +<span class="k">AS</span><span class="w"> </span><span class="k">BEGIN</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="nc">NVARCHAR</span><span class="p">(</span><span class="mi">100</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="nc">TIME</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="k">SET</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nf">CAST</span><span class="p">(</span><span class="nf">GETDATE</span><span class="p">()</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="nc">TIME</span><span class="p">);</span><span class="w"></span> + +<span class="w"> </span><span class="cm">/* Block the ones that aren&#39;t blocked already and maches the time */</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="n">block_cursor</span><span class="w"> </span><span class="nc">CURSOR</span><span class="w"></span> +<span class="w"> </span><span class="k">FOR</span><span class="w"> </span><span class="k">SELECT</span><span class="w"> </span><span class="n">LoginName</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&lt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&gt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"></span> +<span class="w"> </span><span class="k">OPEN</span><span class="w"> </span><span class="n">block_cursor</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">block_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> + +<span class="w"> </span><span class="k">WHILE</span><span class="w"> </span><span class="nb">@@FETCH_STATUS</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"></span> +<span class="w"> </span><span class="k">BEGIN</span><span class="w"></span> +<span class="w"> </span><span class="k">exec</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;ALTER LOGIN &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="s1">&#39; DISABLE;&#39;</span><span class="p">);</span><span class="w"></span> + +<span class="w"> </span><span class="k">print</span><span class="w"> </span><span class="s1">&#39;Bloqued usuario &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">block_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> +<span class="w"> </span><span class="k">END</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">CLOSE</span><span class="w"> </span><span class="n">block_cursor</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="k">DEALLOCATE</span><span class="w"> </span><span class="n">block_cursor</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">UPDATE</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">SET</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&lt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&gt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"></span> + + +<span class="w"> </span><span class="cm">/* Enable up who was blocked */</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="nc">CURSOR</span><span class="w"></span> +<span class="w"> </span><span class="k">FOR</span><span class="w"> </span><span class="k">SELECT</span><span class="w"> </span><span class="n">LoginName</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="p">(</span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">OR</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="p">)</span><span class="w"></span> +<span class="w"> </span><span class="k">OPEN</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> + +<span class="w"> </span><span class="k">WHILE</span><span class="w"> </span><span class="nb">@@FETCH_STATUS</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"></span> +<span class="w"> </span><span class="k">BEGIN</span><span class="w"></span> +<span class="w"> </span><span class="k">exec</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;ALTER LOGIN &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"> </span><span class="o">+</span><span class="s1">&#39; ENABLE;&#39;</span><span class="p">);</span><span class="w"></span> + +<span class="w"> </span><span class="k">print</span><span class="w"> </span><span class="s1">&#39;Unbloqued usuario &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> +<span class="w"> </span><span class="k">END</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">CLOSE</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="k">DEALLOCATE</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">UPDATE</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">SET</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="p">(</span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">OR</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="p">)</span><span class="w"></span> +<span class="k">END</span><span class="p">;</span><span class="w"></span> +</code></pre></div> + +<p>Ok, so now all you have to do, is schedule a job to run that stored procedure from minute to minute. Again, the main idea is tell the procedure when a user must be blocked and when it'll be unblocked. </p> +<div class="highlight"><pre><span></span><code><span class="err"> -- Will block the user protheus from 10 AM till 15 PM</span> +<span class="err"> INSERT INTO dbo.HorariosBloqueio (Id, LoginName, HrInicio, HrTermino) VALUES (NEXT VALUE FOR seq_HorariosBloqueio, &#39;protheus&#39;, &#39;10:00:00&#39;, &#39;15:00:00&#39;);</span> +</code></pre></div>Bloqueando um usuário do SQL Server baseado em uma tabela de horários2020-11-14T07:00:00-03:002020-11-14T07:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-11-14:/pt/blocking-user-on-sql-server-based-on-schedule.html<p>Ok, algum tempo atrás, eu postei sobre como você pode impor limites às conexões do SQL Server utilizando o <a href="https://www.sipmann.com/limiting-connection-resources-sql-server.html#.X6Cz8IhKhPY">Resource Governor</a>. Mas, e se você não pode utilizar ele? Você sempre pode bloquear logins usando uma trigger, mas eu não gosto da ideia de ter um select rodando a cada …</p><p>Ok, algum tempo atrás, eu postei sobre como você pode impor limites às conexões do SQL Server utilizando o <a href="https://www.sipmann.com/limiting-connection-resources-sql-server.html#.X6Cz8IhKhPY">Resource Governor</a>. Mas, e se você não pode utilizar ele? Você sempre pode bloquear logins usando uma trigger, mas eu não gosto da ideia de ter um select rodando a cada login. Então, eu cheguei a esta solução, utilizando uma stored procedure, uma tabela e o Agent.</p> +<p>A ideia principal é armazenar o horário em que um usuário deve ser bloqueado pelo Agent. Abaixo você pode ver a criação da tabela:</p> +<div class="highlight"><pre><span></span><code><span class="k">CREATE</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"> </span><span class="p">(</span><span class="w"></span> +<span class="w"> </span><span class="n">Id</span><span class="w"> </span><span class="nc">INT</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">LoginName</span><span class="w"> </span><span class="nc">NVARCHAR</span><span class="p">(</span><span class="mi">100</span><span class="p">)</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">HrInicio</span><span class="w"> </span><span class="nc">TIME</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"> </span><span class="cm">/* horário de inicio do bloqueio */</span><span class="w"></span> +<span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="nc">TIME</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"> </span><span class="cm">/*horário de termino */</span><span class="w"></span> +<span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="nc">INT</span><span class="w"> </span><span class="k">DEFAULT</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="cm">/* 0 = desbloqueado, 1 = bloqueado */</span><span class="w"></span> +<span class="w"> </span><span class="k">PRIMARY</span><span class="w"> </span><span class="k">KEY</span><span class="w"> </span><span class="p">(</span><span class="n">Id</span><span class="p">)</span><span class="w"></span> +<span class="p">);</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> + +<span class="cm">/* regra para Não bloquear o usuário SA */</span><span class="w"></span> +<span class="k">ALTER</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"></span> +<span class="w"> </span><span class="k">ADD</span><span class="w"> </span><span class="k">CONSTRAINT</span><span class="w"> </span><span class="n">chk_users</span><span class="w"> </span><span class="k">CHECK</span><span class="w"> </span><span class="p">(</span><span class="n">LoginName</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;sa&#39;</span><span class="p">));</span><span class="w"></span> + +<span class="k">ALTER</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"></span> +<span class="w"> </span><span class="k">ADD</span><span class="w"> </span><span class="k">CONSTRAINT</span><span class="w"> </span><span class="n">chk_hora_final_maior</span><span class="w"> </span><span class="k">CHECK</span><span class="w"> </span><span class="p">(</span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="n">HrInicio</span><span class="p">);</span><span class="w"></span> + +<span class="k">ALTER</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"></span> +<span class="w"> </span><span class="k">ADD</span><span class="w"> </span><span class="k">CONSTRAINT</span><span class="w"> </span><span class="n">chk_status_bloqueio</span><span class="w"> </span><span class="k">CHECK</span><span class="w"> </span><span class="p">(</span><span class="n">Bloqueado</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">));</span><span class="w"></span> + +<span class="k">CREATE</span><span class="w"> </span><span class="k">SEQUENCE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">seq_HorariosBloqueio</span><span class="w"> </span><span class="k">START</span><span class="w"> </span><span class="k">WITH</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="n">INCREMENT</span><span class="w"> </span><span class="k">BY</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +</code></pre></div> + +<p>Depois de criar a tabela, vamos verificar a procedure que vai fazer todo o trabalho de habilitar/desabilitar os usuários. Fique ciente que, nesta procedure, eu defini o nome do banco onde a tabela está armazenada. Você pode substituir o nome <code>DBATOOLS</code> pelo o nome da sua base.</p> +<div class="highlight"><pre><span></span><code><span class="k">IF</span><span class="w"> </span><span class="nf">OBJECT_ID</span><span class="p">(</span><span class="s1">&#39;dbo.sp_ValidarLogin&#39;</span><span class="p">)</span><span class="w"> </span><span class="k">IS</span><span class="w"> </span><span class="k">NULL</span><span class="w"></span> +<span class="w"> </span><span class="k">EXEC</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;CREATE PROCEDURE dbo.sp_ValidarLogin AS RETURN 0;&#39;</span><span class="p">);</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> + +<span class="k">CREATE</span><span class="w"> </span><span class="ow">OR</span><span class="w"> </span><span class="k">ALTER</span><span class="w"> </span><span class="k">PROC</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">sp_ValidarLogin</span><span class="w"></span> +<span class="k">AS</span><span class="w"> </span><span class="k">BEGIN</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="nc">NVARCHAR</span><span class="p">(</span><span class="mi">100</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="nc">TIME</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="k">SET</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nf">CAST</span><span class="p">(</span><span class="nf">GETDATE</span><span class="p">()</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="nc">TIME</span><span class="p">);</span><span class="w"></span> + +<span class="w"> </span><span class="cm">/* Bloqueia os que ainda não estiverem bloqueados de acordo com a hora atual */</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="n">block_cursor</span><span class="w"> </span><span class="nc">CURSOR</span><span class="w"></span> +<span class="w"> </span><span class="k">FOR</span><span class="w"> </span><span class="k">SELECT</span><span class="w"> </span><span class="n">LoginName</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&lt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&gt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"></span> +<span class="w"> </span><span class="k">OPEN</span><span class="w"> </span><span class="n">block_cursor</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">block_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> + +<span class="w"> </span><span class="k">WHILE</span><span class="w"> </span><span class="nb">@@FETCH_STATUS</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"></span> +<span class="w"> </span><span class="k">BEGIN</span><span class="w"></span> +<span class="w"> </span><span class="k">exec</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;ALTER LOGIN &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="s1">&#39; DISABLE;&#39;</span><span class="p">);</span><span class="w"></span> + +<span class="w"> </span><span class="k">print</span><span class="w"> </span><span class="s1">&#39;Bloqued usuario &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">block_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> +<span class="w"> </span><span class="k">END</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">CLOSE</span><span class="w"> </span><span class="n">block_cursor</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="k">DEALLOCATE</span><span class="w"> </span><span class="n">block_cursor</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">UPDATE</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">SET</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&lt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&gt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"></span> + + +<span class="w"> </span><span class="cm">/* Libera quem estava bloqueado */</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="nc">CURSOR</span><span class="w"></span> +<span class="w"> </span><span class="k">FOR</span><span class="w"> </span><span class="k">SELECT</span><span class="w"> </span><span class="n">LoginName</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="p">(</span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">OR</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="p">)</span><span class="w"></span> +<span class="w"> </span><span class="k">OPEN</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> + +<span class="w"> </span><span class="k">WHILE</span><span class="w"> </span><span class="nb">@@FETCH_STATUS</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"></span> +<span class="w"> </span><span class="k">BEGIN</span><span class="w"></span> +<span class="w"> </span><span class="k">exec</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;ALTER LOGIN &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"> </span><span class="o">+</span><span class="s1">&#39; ENABLE;&#39;</span><span class="p">);</span><span class="w"></span> + +<span class="w"> </span><span class="k">print</span><span class="w"> </span><span class="s1">&#39;Unbloqued usuario &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> +<span class="w"> </span><span class="k">END</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">CLOSE</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="k">DEALLOCATE</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">UPDATE</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">SET</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="p">(</span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">OR</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="p">)</span><span class="w"></span> +<span class="k">END</span><span class="p">;</span><span class="w"></span> +</code></pre></div> + +<p>Certo, então agora tudo que temos que fazer é definir o job no Agent para rodar a procedure de minuto em minuto. Novamente, a ideia principal é chamar a procedure quando um usuário deve ser bloqueado e quando deve ser desbloqueado.</p> +<div class="highlight"><pre><span></span><code><span class="err"> -- Vai bloquear o usuário protheus das 10 AM até 15 PM</span> +<span class="err"> INSERT INTO dbo.HorariosBloqueio (Id, LoginName, HrInicio, HrTermino) VALUES (NEXT VALUE FOR seq_HorariosBloqueio, &#39;protheus&#39;, &#39;10:00:00&#39;, &#39;15:00:00&#39;);</span> +</code></pre></div>How to set columns on select using Entity Framework2020-10-28T19:00:00-03:002020-10-28T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-28:/en/select_specific_fields_with_efcore.html<p>So, you use Entity Framework Core, and you usually code your selects like the following, maybe you are getting too much data.</p> +<div class="highlight"><pre><span></span><code><span class="kt">var</span> <span class="n">products</span> <span class="p">=</span> <span class="n">Products</span> + <span class="p">.</span><span class="n">Where</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span> <span class="p">&gt;</span> <span class="m">0</span><span class="p">)</span> + <span class="p">.</span><span class="n">OrderBy</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">)</span> + <span class="p">.</span><span class="n">ToList</span><span class="p">()</span> +</code></pre></div> + +<p>Running the query above, on my table, you'll get the following output, take a look …</p><p>So, you use Entity Framework Core, and you usually code your selects like the following, maybe you are getting too much data.</p> +<div class="highlight"><pre><span></span><code><span class="kt">var</span> <span class="n">products</span> <span class="p">=</span> <span class="n">Products</span> + <span class="p">.</span><span class="n">Where</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span> <span class="p">&gt;</span> <span class="m">0</span><span class="p">)</span> + <span class="p">.</span><span class="n">OrderBy</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">)</span> + <span class="p">.</span><span class="n">ToList</span><span class="p">()</span> +</code></pre></div> + +<p>Running the query above, on my table, you'll get the following output, take a look at how many columns you are getting back from your database.</p> +<p><img alt="Screenshot with every single column" src="/images/ef_core_allcolumns.png"></p> +<p>In my case, I only care about the Title, PublishedData, and a small description. So to get back only these fields, we have a few options. In the first one, we'll set the fields and return them as a dynamic object, the second one, is to give the .NET a class to use. </p> +<div class="highlight"><pre><span></span><code><span class="kt">var</span> <span class="n">products</span> <span class="p">=</span> <span class="n">Products</span> + + <span class="p">.</span><span class="n">Select</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="k">new</span> <span class="p">{</span><span class="n">p</span><span class="p">.</span><span class="n">ProductID</span><span class="p">,</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">,</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span><span class="p">,</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitPrice</span><span class="p">})</span> + <span class="c1">//.Select(p =&gt; new ProductDTO {p.ProductID, p.ProductName, p.UnitsInStock, p.UnitPrice})</span> + + <span class="p">.</span><span class="n">Where</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span> <span class="p">&gt;</span> <span class="m">0</span><span class="p">)</span> + <span class="p">.</span><span class="n">OrderBy</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">)</span> + <span class="p">.</span><span class="n">ToList</span><span class="p">()</span> +</code></pre></div> + +<p><img alt="Screenshot with fewer columns and also fewer data size" src="/images/ef_core_less_columns.png"></p>Como definir as colunas no select utilizando Entity Framework2020-10-28T19:00:00-03:002020-10-28T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-28:/pt/select_specific_fields_with_efcore.html<p>Então, você utiliza Entity Framework Core e geralmente faz o seu selecto da seguinte forma, talvez você está retornando muitos dados.</p> +<div class="highlight"><pre><span></span><code><span class="kt">var</span> <span class="n">products</span> <span class="p">=</span> <span class="n">Products</span> + <span class="p">.</span><span class="n">Where</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span> <span class="p">&gt;</span> <span class="m">0</span><span class="p">)</span> + <span class="p">.</span><span class="n">OrderBy</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">)</span> + <span class="p">.</span><span class="n">ToList</span><span class="p">()</span> +</code></pre></div> + +<p>Rodando a query acima, em uma base de testes você obtem o seguinte resultado, veja quantas …</p><p>Então, você utiliza Entity Framework Core e geralmente faz o seu selecto da seguinte forma, talvez você está retornando muitos dados.</p> +<div class="highlight"><pre><span></span><code><span class="kt">var</span> <span class="n">products</span> <span class="p">=</span> <span class="n">Products</span> + <span class="p">.</span><span class="n">Where</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span> <span class="p">&gt;</span> <span class="m">0</span><span class="p">)</span> + <span class="p">.</span><span class="n">OrderBy</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">)</span> + <span class="p">.</span><span class="n">ToList</span><span class="p">()</span> +</code></pre></div> + +<p>Rodando a query acima, em uma base de testes você obtem o seguinte resultado, veja quantas colunas estão retornando da sua base de dados.</p> +<p><img alt="Print com todas as colunas" src="/images/ef_core_allcolumns.png"></p> +<p>No meu caso, eu só pretendo ter de volta as colunas Title, PublishedData e uma pequena descrição. Então para selecionar apenas estes campos, nós temos algumas opções. Na primeira, nós vamos definir os campos e retornar um objeto do tipo Dynamic. A segunda forma, é dar ao .NET o objeto a ser retornado, pode ser por exêmplo um DTO.</p> +<div class="highlight"><pre><span></span><code><span class="kt">var</span> <span class="n">products</span> <span class="p">=</span> <span class="n">Products</span> + + <span class="p">.</span><span class="n">Select</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="k">new</span> <span class="p">{</span><span class="n">p</span><span class="p">.</span><span class="n">ProductID</span><span class="p">,</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">,</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span><span class="p">,</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitPrice</span><span class="p">})</span> + <span class="c1">//.Select(p =&gt; new ProductDTO {p.ProductID, p.ProductName, p.UnitsInStock, p.UnitPrice})</span> + + <span class="p">.</span><span class="n">Where</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span> <span class="p">&gt;</span> <span class="m">0</span><span class="p">)</span> + <span class="p">.</span><span class="n">OrderBy</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">)</span> + <span class="p">.</span><span class="n">ToList</span><span class="p">()</span> +</code></pre></div> + +<p><img alt="Print com menos colunas e também menor quantidade de dados" src="/images/ef_core_less_columns.png"></p>Zabbix Running on Low Memory Mode2020-10-20T19:00:00-03:002020-10-20T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-20:/en/zabbix-running-on-low-memory-mode.html<p>Hey folks, another Zabbix post today. This one it's about increasing the Zabbix Server Cache. It's pretty common (if you have the default settings only) get a warning about your <code>Zabbix value cache running on low memory mode</code> at your dashboard or logs.</p> +<p><img alt="Zabbix Dashboard warning about the memory problem" src="/images/zabbix_low_memory_mode.png"> +<img alt="Zabbix Dashboard cache graph 70% used" src="/images/zabbix_cache_filling.png"></p> +<p>To solve, go back to your Zabbix …</p><p>Hey folks, another Zabbix post today. This one it's about increasing the Zabbix Server Cache. It's pretty common (if you have the default settings only) get a warning about your <code>Zabbix value cache running on low memory mode</code> at your dashboard or logs.</p> +<p><img alt="Zabbix Dashboard warning about the memory problem" src="/images/zabbix_low_memory_mode.png"> +<img alt="Zabbix Dashboard cache graph 70% used" src="/images/zabbix_cache_filling.png"></p> +<p>To solve, go back to your Zabbix config file (<code>zabbix_server.conf</code>) and look for the tag <em>CacheSize</em>. Uncomment it and set to a value bigger than 8M (8M it's the default value). In my case, we set a cache of 100M. After the change, restart the service.</p> +<div class="highlight"><pre><span></span><code><span class="c1">### Option: CacheSize</span> +<span class="c1"># Size of configuration cache, in bytes.</span> +<span class="c1"># Shared memory size for storing host, item and trigger data.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 128K-64G</span> +<span class="c1"># Default:</span> +<span class="na">CacheSize</span><span class="o">=</span><span class="s">100M #uncomment this line</span> +</code></pre></div> + +<p><img alt="Zabbix Dashboard resolved memory problem" src="/images/zabbix_low_memory_solved.png"></p> +<p>See ya folks.</p>Zabbix Running on Low Memory Mode2020-10-20T19:00:00-03:002020-10-20T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-20:/pt/zabbix-running-on-low-memory-mode.html<p>Olá pessoal! Trago hoje outro post sobre Zabbix. Este é sobre aumentar o cache do seu Zabbix Server. É perfeitamente comum (se você roda com as configurações padrões) receber avisos sobre <code>Zabbix value cache running on low memory mode</code> no seu dashboard ou arquivos de log.</p> +<p><img alt="Zabbix Dashboard alertando sobre problemas de memória" src="/images/zabbix_low_memory_mode.png"> +<img alt="Zabbix Dashboard cache gráfico com 70% utilizado" src="/images/zabbix_cache_filling.png"></p> +<p>Para resolver, abra o …</p><p>Olá pessoal! Trago hoje outro post sobre Zabbix. Este é sobre aumentar o cache do seu Zabbix Server. É perfeitamente comum (se você roda com as configurações padrões) receber avisos sobre <code>Zabbix value cache running on low memory mode</code> no seu dashboard ou arquivos de log.</p> +<p><img alt="Zabbix Dashboard alertando sobre problemas de memória" src="/images/zabbix_low_memory_mode.png"> +<img alt="Zabbix Dashboard cache gráfico com 70% utilizado" src="/images/zabbix_cache_filling.png"></p> +<p>Para resolver, abra o seu arquivo de configuração (<code>zabbix_server.conf</code>) e procure pela tag <em>CacheSize</em>. Descomente a linha e defina um valor maior que 8M (8M é o valor padrão). No meu caso, nós configuramos um cache de 100M. Depois da troca, reinicie o serviço para que o mesmo tome efeito.</p> +<div class="highlight"><pre><span></span><code><span class="c1">### Option: CacheSize</span> +<span class="c1"># Size of configuration cache, in bytes.</span> +<span class="c1"># Shared memory size for storing host, item and trigger data.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 128K-64G</span> +<span class="c1"># Default:</span> +<span class="na">CacheSize</span><span class="o">=</span><span class="s">100M #Descomente esta linha</span> +</code></pre></div> + +<p><img alt="Zabbix Dashboard resolved memory problem" src="/images/zabbix_low_memory_solved.png"></p> +<p>Até breve.</p>Monitoring MySQL Replication Status with PowerShell2020-10-14T19:00:00-03:002020-10-14T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-14:/en/monitoring-mysql-replication-with-powershell.html<p>I've been migration some bash scripts that I have to PowerShell, and it's time to migrate a script that monitors the replication of a MySQL database. The credit for the original script goes to <a href="https://handyman.dulare.com/mysql-replication-status-alerts-with-bash-script/">Paweł</a>. It's a simple script where I seek a few tags/fields that we get from …</p><p>I've been migration some bash scripts that I have to PowerShell, and it's time to migrate a script that monitors the replication of a MySQL database. The credit for the original script goes to <a href="https://handyman.dulare.com/mysql-replication-status-alerts-with-bash-script/">Paweł</a>. It's a simple script where I seek a few tags/fields that we get from <code>SHOW SLAVE STATUS\G</code> command, the fields are. <code>Slave_IO_Running</code>, <code>Slave_SQL_Running</code>, and <code>Seconds_Behind_Master</code>. I still need to figure out the proper way to store/read variables like usernames and passwords, if you have any tips, feel free to even make a pull request (<a href="https://github.com/sipmann/PowerShellScripts">here</a>) at the git where I'll store some scripts.</p> +<div class="highlight"><pre><span></span><code><span class="cm">&lt;#</span> +<span class="cm"> Variables definition</span> +<span class="cm">#&gt;</span> +<span class="nv">$MaxSeconds</span> <span class="p">=</span> <span class="n">120</span> <span class="c"># Max seconds behind master allowed</span> +<span class="nv">$MysqlUser</span> <span class="p">=</span> <span class="s1">&#39;root&#39;</span> +<span class="nv">$MysqlPass</span> <span class="p">=</span> <span class="s1">&#39;&#39;</span> + +<span class="nv">$MailTo</span> <span class="p">=</span> <span class="s1">&#39;mauricio@sipmann.com&#39;</span> +<span class="nv">$MailFrom</span> <span class="p">=</span> <span class="s1">&#39;mauricio@sipmann.com&#39;</span> + + +<span class="nv">$data</span> <span class="p">=</span> <span class="p">$(</span><span class="n">mysql</span> <span class="n">-u</span> <span class="nv">$MysqlUser</span> <span class="n">-p</span><span class="s2">&quot;$MysqlPass&quot;</span> <span class="n">-e</span> <span class="s1">&#39;SHOW SLAVE STATUS \G&#39;</span><span class="p">)</span> + +<span class="c">#Debug data</span> +<span class="c">#$data = Get-Content &#39;c:\temp\sampleresult.txt&#39;</span> + +<span class="cm">&lt;# Parse the data #&gt;</span> +<span class="nv">$IORunning</span> <span class="p">=</span> <span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Slave_IO_Running:&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> +<span class="nv">$SQLRunning</span> <span class="p">=</span> <span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Slave_SQL_Running:&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> +<span class="nv">$LastErrNo</span> <span class="p">=</span> <span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Last_Errno&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> +<span class="nv">$SecondsBh</span> <span class="p">=</span> <span class="no">[int]</span><span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Seconds_Behind_Master&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> + +<span class="k">If</span> <span class="p">(</span><span class="nv">$IORunning</span> <span class="o">-Eq</span> <span class="s1">&#39;No&#39;</span> <span class="o">-Or</span> <span class="nv">$SQLRunning</span> <span class="o">-Eq</span> <span class="s1">&#39;No&#39;</span> <span class="o">-Or</span> <span class="nv">$SecondsBh</span> <span class="o">-gt</span> <span class="nv">$MaxSeconds</span><span class="p">)</span> <span class="p">{</span> + <span class="nv">$MailBody</span> <span class="p">=</span> <span class="s1">&#39;&lt;h1&gt;Problema na replicação&lt;/h1&gt;&lt;br&gt;&#39;</span> + + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39; IO Running: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$IORunning</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39; SQL Running: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$SQLRunning</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39;Seconds Behind: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$SecondsBh</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39; Last Err No: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$LastErrNo</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + + <span class="cm">&lt;# Send e-mail, maybe some telegram message here too #&gt;</span> + <span class="nb">Send-MailMessage</span> <span class="n">-To</span> <span class="nv">$MailTo</span> <span class="n">-From</span> <span class="nv">$MailFrom</span> <span class="n">-Subject</span> <span class="s1">&#39;Problemas na replicação&#39;</span> <span class="n">-bodyAsHtml</span> <span class="nv">$MailBody</span> <span class="n">-Credential</span> <span class="p">(</span><span class="nb">Get-Credential</span><span class="p">)</span> <span class="n">-SmtpServer</span> <span class="s1">&#39;smtp.office365.com&#39;</span> <span class="n">-Port</span> <span class="n">587</span> <span class="n">-UseSsl</span> +<span class="p">}</span> <span class="k">Else</span> <span class="p">{</span> + <span class="nb">Write-Host</span> <span class="s2">&quot;Up and running&quot;</span> +<span class="p">}</span> +</code></pre></div>Monitorando status de replicação do MySQL com PowerShell2020-10-14T19:00:00-03:002020-10-14T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-14:/pt/monitoring-mysql-replication-with-powershell.html<p>Tenho migrado alguns scripts bash que tenho para PowerShell, e chegou a vez de migrar um script de monitoramento de replicação do MySQL. Fica como crédito o script original do <a href="https://handyman.dulare.com/mysql-replication-status-alerts-with-bash-script/">Paweł</a>. É um script bem simples onde eu verifico algumas tags resultantes do <code>SHOW SLAVE STATUS\G</code>, são elas. <code>Slave_IO_Running …</code></p><p>Tenho migrado alguns scripts bash que tenho para PowerShell, e chegou a vez de migrar um script de monitoramento de replicação do MySQL. Fica como crédito o script original do <a href="https://handyman.dulare.com/mysql-replication-status-alerts-with-bash-script/">Paweł</a>. É um script bem simples onde eu verifico algumas tags resultantes do <code>SHOW SLAVE STATUS\G</code>, são elas. <code>Slave_IO_Running</code>, <code>Slave_SQL_Running</code> e <code>Seconds_Behind_Master</code>. Ainda preciso verificar formas mais corretas de armazenar/carregar as variáveis como usuários e senha, se tiver alguma dica, fique à vontade para inclusive fazer um pull request (<a href="https://github.com/sipmann/PowerShellScripts">aqui</a>) no repositório onde vou armazenar alguns dos meus scripts.</p> +<div class="highlight"><pre><span></span><code><span class="cm">&lt;#</span> +<span class="cm"> Variables definition</span> +<span class="cm">#&gt;</span> +<span class="nv">$MaxSeconds</span> <span class="p">=</span> <span class="n">120</span> <span class="c"># Max seconds behind master allowed</span> +<span class="nv">$MysqlUser</span> <span class="p">=</span> <span class="s1">&#39;root&#39;</span> +<span class="nv">$MysqlPass</span> <span class="p">=</span> <span class="s1">&#39;&#39;</span> + +<span class="nv">$MailTo</span> <span class="p">=</span> <span class="s1">&#39;mauricio@sipmann.com&#39;</span> +<span class="nv">$MailFrom</span> <span class="p">=</span> <span class="s1">&#39;mauricio@sipmann.com&#39;</span> + + +<span class="nv">$data</span> <span class="p">=</span> <span class="p">$(</span><span class="n">mysql</span> <span class="n">-u</span> <span class="nv">$MysqlUser</span> <span class="n">-p</span><span class="s2">&quot;$MysqlPass&quot;</span> <span class="n">-e</span> <span class="s1">&#39;SHOW SLAVE STATUS \G&#39;</span><span class="p">)</span> + +<span class="c">#Debug data</span> +<span class="c">#$data = Get-Content &#39;c:\temp\sampleresult.txt&#39;</span> + +<span class="cm">&lt;# Parse the data #&gt;</span> +<span class="nv">$IORunning</span> <span class="p">=</span> <span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Slave_IO_Running:&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> +<span class="nv">$SQLRunning</span> <span class="p">=</span> <span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Slave_SQL_Running:&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> +<span class="nv">$LastErrNo</span> <span class="p">=</span> <span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Last_Errno&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> +<span class="nv">$SecondsBh</span> <span class="p">=</span> <span class="no">[int]</span><span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Seconds_Behind_Master&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> + +<span class="k">If</span> <span class="p">(</span><span class="nv">$IORunning</span> <span class="o">-Eq</span> <span class="s1">&#39;No&#39;</span> <span class="o">-Or</span> <span class="nv">$SQLRunning</span> <span class="o">-Eq</span> <span class="s1">&#39;No&#39;</span> <span class="o">-Or</span> <span class="nv">$SecondsBh</span> <span class="o">-gt</span> <span class="nv">$MaxSeconds</span><span class="p">)</span> <span class="p">{</span> + <span class="nv">$MailBody</span> <span class="p">=</span> <span class="s1">&#39;&lt;h1&gt;Problema na replicação&lt;/h1&gt;&lt;br&gt;&#39;</span> + + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39; IO Running: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$IORunning</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39; SQL Running: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$SQLRunning</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39;Seconds Behind: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$SecondsBh</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39; Last Err No: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$LastErrNo</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + + <span class="cm">&lt;# Send e-mail, maybe some telegram message here too #&gt;</span> + <span class="nb">Send-MailMessage</span> <span class="n">-To</span> <span class="nv">$MailTo</span> <span class="n">-From</span> <span class="nv">$MailFrom</span> <span class="n">-Subject</span> <span class="s1">&#39;Problemas na replicação&#39;</span> <span class="n">-bodyAsHtml</span> <span class="nv">$MailBody</span> <span class="n">-Credential</span> <span class="p">(</span><span class="nb">Get-Credential</span><span class="p">)</span> <span class="n">-SmtpServer</span> <span class="s1">&#39;smtp.office365.com&#39;</span> <span class="n">-Port</span> <span class="n">587</span> <span class="n">-UseSsl</span> +<span class="p">}</span> <span class="k">Else</span> <span class="p">{</span> + <span class="nb">Write-Host</span> <span class="s2">&quot;Up and running&quot;</span> +<span class="p">}</span> +</code></pre></div>Microsoft Against Covid2020-10-03T19:00:00-03:002020-10-03T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-03:/en/microsoft-against-covid.html<p>Has your job been affected by covid? Well, last week I've posted on <a href="https://grepora.com/2020/09/17/microsoft-ignite-certification-voucher/">Grepora</a> about a Free Certification Voucher that Microsoft was giving away at the Microsoft Ignite event. After that, I found that they were also giving a huge discount to people who have had their job affected by …</p><p>Has your job been affected by covid? Well, last week I've posted on <a href="https://grepora.com/2020/09/17/microsoft-ignite-certification-voucher/">Grepora</a> about a Free Certification Voucher that Microsoft was giving away at the Microsoft Ignite event. After that, I found that they were also giving a huge discount to people who have had their job affected by covid pandemic. </p> +<p>To see more details about if you were eligible, access <a href="https://docs.microsoft.com/en-us/learn/certifications/skillingoffer">https://docs.microsoft.com/en-us/learn/certifications/skillingoffer</a>.</p>Microsoft Contra Covid2020-10-03T19:00:00-03:002020-10-03T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-03:/pt/microsoft-against-covid.html<p>Você teve seu trabalho afetado pela pandemia do covid? Bom, na última semana eu postei no <a href="https://grepora.com/2020/09/17/microsoft-ignite-certification-voucher/">Grepora</a> sobre um Voucher para certificação gratuita que a Microsoft estava distribuindo durante o evento Microsoft Ignite. Depois disto, eu fiquei sabendo que eles também estão entregando grandes discontos para quem teve o seu …</p><p>Você teve seu trabalho afetado pela pandemia do covid? Bom, na última semana eu postei no <a href="https://grepora.com/2020/09/17/microsoft-ignite-certification-voucher/">Grepora</a> sobre um Voucher para certificação gratuita que a Microsoft estava distribuindo durante o evento Microsoft Ignite. Depois disto, eu fiquei sabendo que eles também estão entregando grandes discontos para quem teve o seu trabalho afetado pela pandemia do covid. </p> +<p>Para saber se você pode receber este desconto, acesse <a href="https://docs.microsoft.com/en-us/learn/certifications/skillingoffer">https://docs.microsoft.com/en-us/learn/certifications/skillingoffer</a>.</p>The power of PowerShell2020-09-21T19:00:00-03:002020-09-21T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-09-21:/en/the-power-of-powershell.html<p>As a long time Linux user, I've automated a few things with bash scripts and stayed away from PowerShell... I've moved to a Windows environment a few years ago and still, haven gave a shot to PS. But why not? I've made a few scripts to automate some tasks at …</p><p>As a long time Linux user, I've automated a few things with bash scripts and stayed away from PowerShell... I've moved to a Windows environment a few years ago and still, haven gave a shot to PS. But why not? I've made a few scripts to automate some tasks at a Protheus server.</p> +<p>I found the PS scripts being easy to read and understand. Bellow, we have a script to remove files filtering their extension (or no extension at all like the following script). </p> +<div class="highlight"><pre><span></span><code><span class="nb">Get-ChildItem</span> <span class="s2">&quot;C:\TOTVS\protheus_data\system&quot;</span> <span class="o">-File</span> <span class="n">-Filter</span> <span class="p">*.</span> <span class="p">|</span> <span class="nb">Move-Item</span> <span class="n">-Force</span> <span class="n">-Destination</span> <span class="p">{</span> + <span class="cm">&lt;# Diretory where the files will be moved. You can use Date formats to help name it #&gt;</span> + <span class="cm">&lt;# LastWriteTime proprtie from the current file #&gt;</span> + <span class="nv">$dir</span> <span class="p">=</span> <span class="s2">&quot;C:\bad_files\{0:yyyy\\MM\\dd}&quot;</span> <span class="o">-f</span> <span class="nv">$_</span><span class="p">.</span><span class="n">LastWriteTime</span> + <span class="nv">$null</span> <span class="p">=</span> <span class="n">mkdir</span> <span class="nv">$dir</span> <span class="n">-Force</span> + <span class="s2">&quot;$dir\</span><span class="p">$(</span><span class="nv">$_</span><span class="p">.</span><span class="n">Name</span><span class="p">)</span><span class="s2">&quot;</span> +<span class="p">}</span> +</code></pre></div> + +<p>Have you ever been in the need to remove files based on other file content? Bello a script where I read a file that has the names of files that I want to remove. </p> +<div class="highlight"><pre><span></span><code><span class="k">foreach</span><span class="p">(</span><span class="nv">$line</span> <span class="k">in</span> <span class="nb">Get-Content</span> <span class="p">.\</span><span class="n">Desktop</span><span class="p">\</span><span class="n">bad_files</span><span class="p">.</span><span class="n">txt</span><span class="p">)</span> <span class="p">{</span> + <span class="k">if</span> <span class="p">(</span><span class="nb">Test-Path</span><span class="p">(</span><span class="s1">&#39;\\x.y.z.a\c$\TOTVS\protheus_data\xmls\&#39;</span><span class="p">+</span><span class="nv">$line</span><span class="p">+</span><span class="s1">&#39;.xml&#39;</span><span class="p">))</span> <span class="p">{</span> + <span class="nb">Remove-Item</span><span class="p">(</span><span class="s1">&#39;\\x.y.z.a\c$\TOTVS\protheus_data\xmls\&#39;</span><span class="p">+</span><span class="nv">$line</span><span class="p">+</span><span class="s1">&#39;.xml&#39;</span><span class="p">)</span> + <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> + <span class="nb">echo </span><span class="nv">$line</span> <span class="p">+</span> <span class="s1">&#39; - File not found&#39;</span> + <span class="p">}</span> +<span class="p">}</span> +</code></pre></div> + +<p>And a bonus script to stop/start services (if you handle some Protheus Server, you know why I do that).</p> +<div class="highlight"><pre><span></span><code><span class="nv">$servicesNames</span> <span class="p">=</span> <span class="s1">&#39;app_main&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker1&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker2&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker3&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker4&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker5&#39;</span> + +<span class="nb">Write-host</span> <span class="s2">&quot;Stoping Services&quot;</span> +<span class="nb">Write-host</span> <span class="s2">&quot;--------------------------&quot;</span> + +<span class="k">foreach</span> <span class="p">(</span><span class="nv">$srv</span> <span class="k">in</span> <span class="nv">$servicesNames</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Write-host</span> <span class="s2">&quot;Stopping: &quot;</span> <span class="p">+</span> <span class="nv">$srv</span> + <span class="nv">$SrvPID</span> <span class="p">=</span> <span class="p">(</span><span class="nb">get-wmiobject</span> <span class="n">win32_service</span> <span class="p">|</span> <span class="nb">where </span><span class="p">{</span> <span class="nv">$_</span><span class="p">.</span><span class="n">name</span> <span class="o">-eq</span> <span class="nv">$srv</span><span class="p">}).</span><span class="n">processID</span> + <span class="nb">Write-host</span> <span class="s2">&quot;PID: &quot;</span> <span class="p">+</span> <span class="nv">$SrvPID</span> + + <span class="cm">&lt;# Force if the proccess is stucked #&gt;</span> + <span class="nb">Stop-Process</span> <span class="nv">$SrvPID</span> <span class="n">-Force</span> + <span class="nb">Write-host</span> <span class="s2">&quot;PDI &quot;</span> <span class="p">+</span> <span class="nv">$SrvPID</span> <span class="p">+</span> <span class="s2">&quot; stopped&quot;</span> +<span class="p">}</span> + + +<span class="nb">Write-host</span> <span class="s2">&quot;Starting Services&quot;</span> +<span class="nb">Write-host</span> <span class="s2">&quot;--------------------------&quot;</span> + +<span class="k">foreach</span> <span class="p">(</span><span class="nv">$srv</span> <span class="k">in</span> <span class="nv">$servicesNames</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Write-host</span> <span class="s2">&quot;Starting: &quot;</span> <span class="p">+</span> <span class="nv">$srv</span> + <span class="nb">Start-Service</span> <span class="nv">$srv</span> +<span class="p">}</span> +</code></pre></div> + +<p>Do you have any automated script? Share with us :)</p>O poder do PowerShell2020-09-21T19:00:00-03:002020-09-21T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-09-21:/pt/the-power-of-powershell.html<p>Como um usuário linux por muito tempo, eu automatizei algumas tarefas com scripts bash e fiquei longe do PowerShell... Voltei a utilizar Windows alguns anos atrás e ainda assim, não dei uma chance ao PS. Mas porque não? Eu fiz alguns scripts para automatizar algumas tarefas em um servidor Protheus …</p><p>Como um usuário linux por muito tempo, eu automatizei algumas tarefas com scripts bash e fiquei longe do PowerShell... Voltei a utilizar Windows alguns anos atrás e ainda assim, não dei uma chance ao PS. Mas porque não? Eu fiz alguns scripts para automatizar algumas tarefas em um servidor Protheus.</p> +<p>Eu acabei achando os scripts PS de fácil leitura e entendimento. Abaixo, nós temos um script para remover arquivos filtrando pela sua extensão (ou sem extensão alguma no caso do script em questão).</p> +<div class="highlight"><pre><span></span><code><span class="nb">Get-ChildItem</span> <span class="s2">&quot;C:\TOTVS\protheus_data\system&quot;</span> <span class="o">-File</span> <span class="n">-Filter</span> <span class="p">*.</span> <span class="p">|</span> <span class="nb">Move-Item</span> <span class="n">-Force</span> <span class="n">-Destination</span> <span class="p">{</span> + <span class="cm">&lt;# Diretório ao qual os arquivos vão ser movidos. Você pode utilizar formatos de data para nomear os diretórios #&gt;</span> + <span class="cm">&lt;# LastWriteTime é a propriedade do arquivo corrent #&gt;</span> + <span class="nv">$dir</span> <span class="p">=</span> <span class="s2">&quot;C:\bad_files\{0:yyyy\\MM\\dd}&quot;</span> <span class="o">-f</span> <span class="nv">$_</span><span class="p">.</span><span class="n">LastWriteTime</span> + <span class="nv">$null</span> <span class="p">=</span> <span class="n">mkdir</span> <span class="nv">$dir</span> <span class="n">-Force</span> + <span class="s2">&quot;$dir\</span><span class="p">$(</span><span class="nv">$_</span><span class="p">.</span><span class="n">Name</span><span class="p">)</span><span class="s2">&quot;</span> +<span class="p">}</span> +</code></pre></div> + +<p>Você já precisou remover arquivos baseado no conteúdo de outro arquivo? Abaixo um script onde eu leio um arquivo que contem os nomes de arquivos que eu desejo remover. </p> +<div class="highlight"><pre><span></span><code><span class="k">foreach</span><span class="p">(</span><span class="nv">$line</span> <span class="k">in</span> <span class="nb">Get-Content</span> <span class="p">.\</span><span class="n">Desktop</span><span class="p">\</span><span class="n">bad_files</span><span class="p">.</span><span class="n">txt</span><span class="p">)</span> <span class="p">{</span> + <span class="k">if</span> <span class="p">(</span><span class="nb">Test-Path</span><span class="p">(</span><span class="s1">&#39;\\x.y.z.a\c$\TOTVS\protheus_data\xmls\&#39;</span><span class="p">+</span><span class="nv">$line</span><span class="p">+</span><span class="s1">&#39;.xml&#39;</span><span class="p">))</span> <span class="p">{</span> + <span class="nb">Remove-Item</span><span class="p">(</span><span class="s1">&#39;\\x.y.z.a\c$\TOTVS\protheus_data\xmls\&#39;</span><span class="p">+</span><span class="nv">$line</span><span class="p">+</span><span class="s1">&#39;.xml&#39;</span><span class="p">)</span> + <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> + <span class="nb">echo </span><span class="nv">$line</span> <span class="p">+</span> <span class="s1">&#39; - File not found&#39;</span> + <span class="p">}</span> +<span class="p">}</span> +</code></pre></div> + +<p>E um script bonus para parar e iniciar serviços (se você gerencia um servidor Protheus, você sabe o porque eu faço isto).</p> +<div class="highlight"><pre><span></span><code><span class="nv">$servicesNames</span> <span class="p">=</span> <span class="s1">&#39;app_main&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker1&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker2&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker3&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker4&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker5&#39;</span> + +<span class="nb">Write-host</span> <span class="s2">&quot;Parando Serviços&quot;</span> +<span class="nb">Write-host</span> <span class="s2">&quot;--------------------------&quot;</span> + +<span class="k">foreach</span> <span class="p">(</span><span class="nv">$srv</span> <span class="k">in</span> <span class="nv">$servicesNames</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Write-host</span> <span class="s2">&quot;Parando: &quot;</span> <span class="p">+</span> <span class="nv">$srv</span> + <span class="nv">$SrvPID</span> <span class="p">=</span> <span class="p">(</span><span class="nb">get-wmiobject</span> <span class="n">win32_service</span> <span class="p">|</span> <span class="nb">where </span><span class="p">{</span> <span class="nv">$_</span><span class="p">.</span><span class="n">name</span> <span class="o">-eq</span> <span class="nv">$srv</span><span class="p">}).</span><span class="n">processID</span> + <span class="nb">Write-host</span> <span class="s2">&quot;PID: &quot;</span> <span class="p">+</span> <span class="nv">$SrvPID</span> + + <span class="cm">&lt;# Força a parada caso o serviço esteja travado #&gt;</span> + <span class="nb">Stop-Process</span> <span class="nv">$ServicePID</span> <span class="n">-Force</span> + <span class="nb">Write-host</span> <span class="s2">&quot;PDI &quot;</span> <span class="p">+</span> <span class="nv">$SrvPID</span> <span class="p">+</span> <span class="s2">&quot; parado&quot;</span> +<span class="p">}</span> + + +<span class="nb">Write-host</span> <span class="s2">&quot;Inicializando Serviços&quot;</span> +<span class="nb">Write-host</span> <span class="s2">&quot;--------------------------&quot;</span> + +<span class="k">foreach</span> <span class="p">(</span><span class="nv">$srv</span> <span class="k">in</span> <span class="nv">$servicesNames</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Write-host</span> <span class="s2">&quot;Inicializando: &quot;</span> <span class="p">+</span> <span class="nv">$srv</span> + <span class="nb">Start-Service</span> <span class="nv">$srv</span> +<span class="p">}</span> +</code></pre></div> + +<p>Você tem algum script de automação? Compartilhe conosco :)</p>Top Level Statement in C# 92020-07-29T19:00:00-03:002020-07-29T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-07-29:/en/top_level_statement_csharp_9.html<p>Hey folks, I'm coming along to tell you a few things about the new feature of C# 9. Every time you want to start a new project, you always have the same Main File, with the same structure. At the next version of C# (version 9), we'll have a new …</p><p>Hey folks, I'm coming along to tell you a few things about the new feature of C# 9. Every time you want to start a new project, you always have the same Main File, with the same structure. At the next version of C# (version 9), we'll have a new feature called <code>Top Level Statement</code>. With that, we'll be able to code our app without any namespace/class/public void static main structure. Take a look at the code below.</p> +<div class="highlight"><pre><span></span><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span> + +<span class="n">Console</span><span class="p">.</span><span class="n">WriteLine</span><span class="p">(</span><span class="s">&quot;Hello World!&quot;</span><span class="p">);</span> +</code></pre></div> + +<p>It looks pretty simple, but with this, you can play around with your code, and even code a simple/tiny Web API. To start playing with the new features, firstly download the <a href="https://dotnet.microsoft.com/download/dotnet/5.0">.net 5 SDK</a> and change your <code>.csproj</code> file to target the .net 5 and language preview like bellow.</p> +<div class="highlight"><pre><span></span><code><span class="nt">&lt;Project</span> <span class="na">Sdk=</span><span class="s">&quot;Microsoft.NET.Sdk&quot;</span><span class="nt">&gt;</span> + <span class="nt">&lt;PropertyGroup&gt;</span> + <span class="nt">&lt;OutputType&gt;</span>Exe<span class="nt">&lt;/OutputType&gt;</span> + <span class="nt">&lt;TargetFramework&gt;</span>net5.0<span class="nt">&lt;/TargetFramework&gt;</span> + <span class="nt">&lt;LangVersion&gt;</span>preview<span class="nt">&lt;/LangVersion&gt;</span> + <span class="nt">&lt;/PropertyGroup&gt;</span> +<span class="nt">&lt;/Project&gt;</span> +</code></pre></div> + +<p>And you're ready to play with the awesome features available in the preview. Let's code a way to get the image of the day from NASA API and print the Picture of the Day. No awesome code here, it's really a way to show how simple a simple call could be. After here, why not save the image in a file? Maybe send the file over telegram?</p> +<div class="highlight"><pre><span></span><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Net.Http</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Text.Json</span><span class="p">;</span> + +<span class="kt">var</span> <span class="n">API</span> <span class="p">=</span> <span class="s">&quot;https://api.nasa.gov/planetary/apod?hd=true&amp;api_key=DEMO_KEY&quot;</span><span class="p">;</span> +<span class="kt">var</span> <span class="n">cli</span> <span class="p">=</span> <span class="k">new</span> <span class="n">HttpClient</span><span class="p">();</span> + +<span class="kt">var</span> <span class="n">response</span> <span class="p">=</span> <span class="k">await</span> <span class="n">cli</span><span class="p">.</span><span class="n">GetAsync</span><span class="p">(</span><span class="n">API</span><span class="p">);</span> +<span class="kt">var</span> <span class="n">data</span> <span class="p">=</span> <span class="n">JsonSerializer</span><span class="p">.</span><span class="n">Deserialize</span><span class="p">&lt;</span><span class="n">NasaApi</span><span class="p">&gt;(</span><span class="k">await</span> <span class="n">response</span><span class="p">.</span><span class="n">Content</span><span class="p">.</span><span class="n">ReadAsStringAsync</span><span class="p">());</span> + +<span class="n">Console</span><span class="p">.</span><span class="n">WriteLine</span><span class="p">(</span><span class="n">data</span><span class="p">.</span><span class="n">Url</span><span class="p">);</span> +</code></pre></div> + +<p>That's it for today folks. Keep an eye open for the awesome features C# 9 will bring to us, there's plenty more features already available.</p>Top Level Statement no C# 92020-07-29T19:00:00-03:002020-07-29T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-07-29:/pt/top_level_statement_csharp_9.html<p>Olá pessoal, venho hoje falar sobre uma novidade que estará disponível na versão 9 do C#. Toda vez que você deseja criar um novo projeto, você sempre tem o mesmo arquivo Main, com a mesma estrutura. Na próxima versão do C# (versão 9), nós teremos uma nova funcionalidade chamada <code>Top …</code></p><p>Olá pessoal, venho hoje falar sobre uma novidade que estará disponível na versão 9 do C#. Toda vez que você deseja criar um novo projeto, você sempre tem o mesmo arquivo Main, com a mesma estrutura. Na próxima versão do C# (versão 9), nós teremos uma nova funcionalidade chamada <code>Top Level Statement</code>. Com isto, poderemos programar a nossa aplicação sem toda aquela estrutura de <code>namespace/class/public void static main</code>. Veja o código abaixo.</p> +<div class="highlight"><pre><span></span><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span> + +<span class="n">Console</span><span class="p">.</span><span class="n">WriteLine</span><span class="p">(</span><span class="s">&quot;Hello World!&quot;</span><span class="p">);</span> +</code></pre></div> + +<p>Parece muito simples, não é? Com isto, você pode brincar com seu código e até mesmo programar uma pequena WEB API. Para começar a brincar com estas novas <em>features</em>, primeiramente faça o download do preview do <a href="https://dotnet.microsoft.com/download/dotnet/5.0">.net 5 SDK</a> e modifique o seu arquivo <code>.csproj</code> para apontar o framework para <code>.net5.0</code> e a versão de preview da linguagem. Abaixo como uma aplicação de console deve ficar.</p> +<div class="highlight"><pre><span></span><code><span class="nt">&lt;Project</span> <span class="na">Sdk=</span><span class="s">&quot;Microsoft.NET.Sdk&quot;</span><span class="nt">&gt;</span> + <span class="nt">&lt;PropertyGroup&gt;</span> + <span class="nt">&lt;OutputType&gt;</span>Exe<span class="nt">&lt;/OutputType&gt;</span> + <span class="nt">&lt;TargetFramework&gt;</span>net5.0<span class="nt">&lt;/TargetFramework&gt;</span> + <span class="nt">&lt;LangVersion&gt;</span>preview<span class="nt">&lt;/LangVersion&gt;</span> + <span class="nt">&lt;/PropertyGroup&gt;</span> +<span class="nt">&lt;/Project&gt;</span> +</code></pre></div> + +<p>E assim você está pronto para brincar com as novas funcionalidades que estão disponíveis na versão preview. Vamos programar uma aplicação simples que faz uma requisição na API da NASA e printe a Imagem do Dia no console. Não é nenhum código mirabolante, é simplesmente para exemplificar o quão simples uma simples chamada de API pode ser. Feito isto, porque não salvar a imagem como um arquivo? Ou então enviar essa imagem via telegram?</p> +<div class="highlight"><pre><span></span><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Net.Http</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Text.Json</span><span class="p">;</span> + +<span class="kt">var</span> <span class="n">API</span> <span class="p">=</span> <span class="s">&quot;https://api.nasa.gov/planetary/apod?hd=true&amp;api_key=DEMO_KEY&quot;</span><span class="p">;</span> +<span class="kt">var</span> <span class="n">cli</span> <span class="p">=</span> <span class="k">new</span> <span class="n">HttpClient</span><span class="p">();</span> + +<span class="kt">var</span> <span class="n">response</span> <span class="p">=</span> <span class="k">await</span> <span class="n">cli</span><span class="p">.</span><span class="n">GetAsync</span><span class="p">(</span><span class="n">API</span><span class="p">);</span> +<span class="kt">var</span> <span class="n">data</span> <span class="p">=</span> <span class="n">JsonSerializer</span><span class="p">.</span><span class="n">Deserialize</span><span class="p">&lt;</span><span class="n">NasaApi</span><span class="p">&gt;(</span><span class="k">await</span> <span class="n">response</span><span class="p">.</span><span class="n">Content</span><span class="p">.</span><span class="n">ReadAsStringAsync</span><span class="p">());</span> + +<span class="n">Console</span><span class="p">.</span><span class="n">WriteLine</span><span class="p">(</span><span class="n">data</span><span class="p">.</span><span class="n">Url</span><span class="p">);</span> +</code></pre></div> + +<p>Por hoje é isso. Fique de olho nas novas features que o C# 9 vai nos trazer. Já temos várias disponíveis hoje para testar, esta é apenas uma delas.</p>Zabbix poller processes more than 75%2020-07-02T19:00:00-03:002020-07-02T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-07-02:/en/zabbix-poller-processes-more-than-75.html<p>Hey folks, this is the third post about tweaking the Zabbix configurations. All changes that I've suggested here were based on a Zabbix Server with 50+ hosts. Another thing that can happen to your server, it's the poller get overwhelmed by the amount of servers that need to be polled …</p><p>Hey folks, this is the third post about tweaking the Zabbix configurations. All changes that I've suggested here were based on a Zabbix Server with 50+ hosts. Another thing that can happen to your server, it's the poller get overwhelmed by the amount of servers that need to be polled plus the ones that are not responding. Bellow two images where you can see the log and the graphic where you can see the usage percent. </p> +<p><img alt="Dashboard log about the poller processes" src="/images/zabbix_pooler.png"></p> +<p><img alt="Graph showing the utilization percent of each collector" src="/images/zabbix_pooler_3.png"></p> +<p>To solve, let's go back to the <code>zabbix_server.conf</code> file and find two variables, <code>StartPollers</code> and <code>StartPollersUnreachable</code>. Increase them as needed. There's no magic number, you must see what works for you. But keep in mind that the <code>StartPollersUnreachable</code> is responsible for that host that can't be "reached" (of course) and will hold your poller more time.</p> +<div class="highlight"><pre><span></span><code><span class="c1">### Option: StartPollers</span> +<span class="c1"># Number of pre-forked instances of pollers.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 0-1000</span> +<span class="c1"># Default:</span> +<span class="na">StartPollers</span><span class="o">=</span><span class="s">20</span> + +<span class="c1">#...</span> + +<span class="c1">### Option: StartPollersUnreachable</span> +<span class="c1"># Number of pre-forked instances of pollers for unreachable hosts (including IPMI and Java).</span> +<span class="c1"># At least one poller for unreachable hosts must be running if regular, IPMI or Java pollers</span> +<span class="c1"># are started.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 0-1000</span> +<span class="c1"># Default:</span> +<span class="na">StartPollersUnreachable</span><span class="o">=</span><span class="s">5</span> +</code></pre></div> + +<p>After the change, restart the server and wait a few moments and take a look again at your dashboard. Bellow the effect that I've got.</p> +<p><img alt="Graph showing the new utilization percent of the processes after the changes" src="/images/zabbix_pooler_4.png"></p>Zabbix poller processes more than 75%2020-07-02T19:00:00-03:002020-07-02T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-07-02:/pt/zabbix-poller-processes-more-than-75.html<p>Este é o terceiro post sobre configurações para o Zabbix. Todas as alterações que eu sugiro nestes posts, são baseadas em um servidor com 50+ hosts. Outro problema que pode ocorrer em seu servidor, é o poller de informações ficar sobrecarregado pela quantidade de servidores que ele precisa pegar carga …</p><p>Este é o terceiro post sobre configurações para o Zabbix. Todas as alterações que eu sugiro nestes posts, são baseadas em um servidor com 50+ hosts. Outro problema que pode ocorrer em seu servidor, é o poller de informações ficar sobrecarregado pela quantidade de servidores que ele precisa pegar carga de informações juntamente com os servidores que não respondem a requisição. Abaixo duas imagens onde você pode ver o log e um gráfico onde aparecem os percentuais de uso dos poller. </p> +<p><img alt="Dashboard log sobre o processo do poller" src="/images/zabbix_pooler.png"></p> +<p><img alt="Gráfico mostrando o percentual de utilização de cada coletor" src="/images/zabbix_pooler_3.png"></p> +<p>Para resolver o problema acima, vamos voltar ao arquivo de configuração <code>zabbix_server.conf</code> e localizar duas variáveis, <code>StartPollers</code> e <code>StartPollersUnreachable</code>. Aumente o valor delas conforme necessário. Não existe um número mágico, você deve verificar o que melhor funciona para você. Mas tenha em mente que <code>StartPollersUnreachable</code> é responsável por aqueles hosts que não respondem ou não são localizados e irão segurar a thread do poller por mais tempo, causando uma fila e um maior processamento/tempo de atualização.</p> +<div class="highlight"><pre><span></span><code><span class="c1">### Option: StartPollers</span> +<span class="c1"># Number of pre-forked instances of pollers.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 0-1000</span> +<span class="c1"># Default:</span> +<span class="na">StartPollers</span><span class="o">=</span><span class="s">20</span> + +<span class="c1">#...</span> + +<span class="c1">### Option: StartPollersUnreachable</span> +<span class="c1"># Number of pre-forked instances of pollers for unreachable hosts (including IPMI and Java).</span> +<span class="c1"># At least one poller for unreachable hosts must be running if regular, IPMI or Java pollers</span> +<span class="c1"># are started.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 0-1000</span> +<span class="c1"># Default:</span> +<span class="na">StartPollersUnreachable</span><span class="o">=</span><span class="s">5</span> +</code></pre></div> + +<p>Depois da alteração, reinicie o serviço e espere alguns momentos e veja o seu dashboard novamente. Abaixo o efeito que a troca teve em um dos servidores que acompanho.</p> +<p><img alt="Gráfico mostrando os novos percentuais de utilização dos processos após as alterações" src="/images/zabbix_pooler_4.png"></p>Monitoring a Website heath with Azure Functions2020-06-22T19:00:00-03:002020-06-22T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-06-22:/en/monitoring-website-heath-with-azure-functions.html<p>Sometimes you get your self in need to monitor a website's health or it's content for changes. Of course, there's plenty of options out there, but for the sake of curiosity, let's code our own to see what we can do. First things first. Everything you'll see here, you can …</p><p>Sometimes you get your self in need to monitor a website's health or it's content for changes. Of course, there's plenty of options out there, but for the sake of curiosity, let's code our own to see what we can do. First things first. Everything you'll see here, you can achieve with the <a href="https://azure.microsoft.com/free/">free tier</a> of azure.</p> +<p>The main idea of our app will be to monitor website health (status code). To create a new Azure Function Project, follow the steps below.</p> +<p><img alt="Steps to create a azure function project" src="/images/azure_functions.gif"></p> +<p>After creating the project, you'll have a few files. Open your main file and start coding. The main file will have a function called <code>Run</code> and you can code your request method. I've created an <code>async</code> method to make the request and log the output at the console. The full code you can see below.</p> +<div class="highlight"><pre><span></span><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Linq</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Net.Http</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Threading.Tasks</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">Microsoft.Azure.WebJobs</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">Microsoft.Azure.WebJobs.Host</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">Microsoft.Extensions.Logging</span><span class="p">;</span> + +<span class="k">namespace</span> <span class="nn">Sipmann.CheckMySite</span> +<span class="p">{</span> + <span class="k">public</span> <span class="k">static</span> <span class="k">class</span> <span class="nc">HttpCheck</span> + <span class="p">{</span> + + <span class="k">private</span> <span class="k">static</span> <span class="k">async</span> <span class="n">Task</span> <span class="nf">GetTask</span><span class="p">(</span><span class="kt">string</span> <span class="n">url</span><span class="p">,</span> <span class="n">ILogger</span> <span class="n">log</span><span class="p">)</span> + <span class="p">{</span> + <span class="kt">var</span> <span class="n">request</span> <span class="p">=</span> <span class="k">new</span> <span class="n">HttpRequestMessage</span><span class="p">(</span><span class="n">HttpMethod</span><span class="p">.</span><span class="n">Get</span><span class="p">,</span> <span class="n">url</span><span class="p">);</span> + + <span class="kt">var</span> <span class="n">client</span> <span class="p">=</span> <span class="k">new</span> <span class="n">HttpClient</span><span class="p">();</span> + <span class="kt">var</span> <span class="n">response</span> <span class="p">=</span> <span class="k">await</span> <span class="n">client</span><span class="p">.</span><span class="n">SendAsync</span><span class="p">(</span><span class="n">request</span><span class="p">);</span> + + <span class="k">if</span> <span class="p">(</span><span class="n">response</span><span class="p">.</span><span class="n">IsSuccessStatusCode</span><span class="p">)</span> + <span class="p">{</span> + <span class="n">log</span><span class="p">.</span><span class="n">LogInformation</span><span class="p">(</span><span class="err">$</span><span class="s">&quot;URL ${url} esta OK&quot;</span><span class="p">);</span> + <span class="p">}</span> + <span class="k">else</span> + <span class="p">{</span> + <span class="n">log</span><span class="p">.</span><span class="n">LogInformation</span><span class="p">(</span><span class="err">$</span><span class="s">&quot;URL ${url} não esta OK&quot;</span><span class="p">);</span> + <span class="p">}</span> + <span class="p">}</span> + +<span class="na"> [FunctionName(&quot;HttpCheck&quot;)]</span> + <span class="k">public</span> <span class="k">static</span> <span class="k">void</span> <span class="nf">Run</span><span class="p">([</span><span class="n">TimerTrigger</span><span class="p">(</span><span class="s">&quot;0 */5 * * * *&quot;</span><span class="p">)]</span><span class="n">TimerInfo</span> <span class="n">myTimer</span><span class="p">,</span> <span class="n">ILogger</span> <span class="n">log</span><span class="p">)</span> + <span class="p">{</span> + <span class="kt">var</span> <span class="n">urls</span> <span class="p">=</span> <span class="k">new</span><span class="p">[]{</span><span class="s">&quot;https://www.sipmann.com&quot;</span><span class="p">,</span> <span class="s">&quot;https://www.canezecanez.com.br&quot;</span><span class="p">};</span> + + <span class="c1">// Start every request and wait for them all to complete</span> + <span class="n">Task</span><span class="p">.</span><span class="n">WaitAll</span><span class="p">(</span><span class="n">urls</span><span class="p">.</span><span class="n">Select</span><span class="p">(</span><span class="n">url</span> <span class="p">=&gt;</span> <span class="n">GetTask</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">log</span><span class="p">)).</span><span class="n">ToArray</span><span class="p">());</span> + <span class="n">log</span><span class="p">.</span><span class="n">LogInformation</span><span class="p">(</span><span class="err">$</span><span class="s">&quot;Finalizou a fila&quot;</span><span class="p">);</span> + <span class="p">}</span> + <span class="p">}</span> +<span class="p">}</span> +</code></pre></div> + +<p>Now you can enhance the function and maybe send some alerts like a Telegram message when one of your sites went down.</p>Monitorando a disponibilidade de um Website com Azure Functions2020-06-22T19:00:00-03:002020-06-22T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-06-22:/pt/monitoring-website-heath-with-azure-functions.html<p>Algumas vezes você se depara com a necessidade de monitorar a disponibilidade de um website ou mudanças em seu conteúdo. É claro que temos diversas opções disponíveis no mercado, mas para fins de curiosidade, vamos programar o nosso próprio e ver o que podemos fazer. Primeiramente, tudo que você ver …</p><p>Algumas vezes você se depara com a necessidade de monitorar a disponibilidade de um website ou mudanças em seu conteúdo. É claro que temos diversas opções disponíveis no mercado, mas para fins de curiosidade, vamos programar o nosso próprio e ver o que podemos fazer. Primeiramente, tudo que você ver aqui, você pode utilizar o <a href="https://azure.microsoft.com/free/">tier gratuito</a> da Azure.</p> +<p>A ideia principal da nossa aplicação vai ser monitorar a disponibilidade do website (status code). Para criar um projeto de Azure Function, siga os passos abaixo.</p> +<p><img alt="Passos para criar um projeto Azure Functions" src="/images/azure_functions.gif"></p> +<p>Depois de criar o projeto, você vai ter alguns arquivos. Abra o arquivo principal (<code>HttpCheck.cs</code> no meu caso) e começe a programar. O arquivo principal terá uma função chamada <code>Run</code> e você pode progamar nela o seu request. Eu criei um método <code>async</code> para fazer as requisições e printar a saída diretamente no console. O código completo pode ser visto abaixo.</p> +<div class="highlight"><pre><span></span><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Linq</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Net.Http</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Threading.Tasks</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">Microsoft.Azure.WebJobs</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">Microsoft.Azure.WebJobs.Host</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">Microsoft.Extensions.Logging</span><span class="p">;</span> + +<span class="k">namespace</span> <span class="nn">Sipmann.CheckMySite</span> +<span class="p">{</span> + <span class="k">public</span> <span class="k">static</span> <span class="k">class</span> <span class="nc">HttpCheck</span> + <span class="p">{</span> + + <span class="k">private</span> <span class="k">static</span> <span class="k">async</span> <span class="n">Task</span> <span class="nf">GetTask</span><span class="p">(</span><span class="kt">string</span> <span class="n">url</span><span class="p">,</span> <span class="n">ILogger</span> <span class="n">log</span><span class="p">)</span> + <span class="p">{</span> + <span class="kt">var</span> <span class="n">request</span> <span class="p">=</span> <span class="k">new</span> <span class="n">HttpRequestMessage</span><span class="p">(</span><span class="n">HttpMethod</span><span class="p">.</span><span class="n">Get</span><span class="p">,</span> <span class="n">url</span><span class="p">);</span> + + <span class="kt">var</span> <span class="n">client</span> <span class="p">=</span> <span class="k">new</span> <span class="n">HttpClient</span><span class="p">();</span> + <span class="kt">var</span> <span class="n">response</span> <span class="p">=</span> <span class="k">await</span> <span class="n">client</span><span class="p">.</span><span class="n">SendAsync</span><span class="p">(</span><span class="n">request</span><span class="p">);</span> + + <span class="k">if</span> <span class="p">(</span><span class="n">response</span><span class="p">.</span><span class="n">IsSuccessStatusCode</span><span class="p">)</span> + <span class="p">{</span> + <span class="n">log</span><span class="p">.</span><span class="n">LogInformation</span><span class="p">(</span><span class="err">$</span><span class="s">&quot;URL ${url} esta OK&quot;</span><span class="p">);</span> + <span class="p">}</span> + <span class="k">else</span> + <span class="p">{</span> + <span class="n">log</span><span class="p">.</span><span class="n">LogInformation</span><span class="p">(</span><span class="err">$</span><span class="s">&quot;URL ${url} não esta OK&quot;</span><span class="p">);</span> + <span class="p">}</span> + <span class="p">}</span> + +<span class="na"> [FunctionName(&quot;HttpCheck&quot;)]</span> + <span class="k">public</span> <span class="k">static</span> <span class="k">void</span> <span class="nf">Run</span><span class="p">([</span><span class="n">TimerTrigger</span><span class="p">(</span><span class="s">&quot;0 */5 * * * *&quot;</span><span class="p">)]</span><span class="n">TimerInfo</span> <span class="n">myTimer</span><span class="p">,</span> <span class="n">ILogger</span> <span class="n">log</span><span class="p">)</span> + <span class="p">{</span> + <span class="c1">// URL a verificar a saúde</span> + <span class="kt">var</span> <span class="n">urls</span> <span class="p">=</span> <span class="k">new</span><span class="p">[]{</span><span class="s">&quot;https://www.sipmann.com&quot;</span><span class="p">,</span> <span class="s">&quot;https://www.canezecanez.com.br&quot;</span><span class="p">};</span> + + <span class="c1">// Starta cada request e aguarda todos de uma vez só</span> + <span class="n">Task</span><span class="p">.</span><span class="n">WaitAll</span><span class="p">(</span><span class="n">urls</span><span class="p">.</span><span class="n">Select</span><span class="p">(</span><span class="n">url</span> <span class="p">=&gt;</span> <span class="n">GetTask</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">log</span><span class="p">)).</span><span class="n">ToArray</span><span class="p">());</span> + <span class="n">log</span><span class="p">.</span><span class="n">LogInformation</span><span class="p">(</span><span class="err">$</span><span class="s">&quot;Finalizou a fila&quot;</span><span class="p">);</span> + <span class="p">}</span> + <span class="p">}</span> +<span class="p">}</span> +</code></pre></div> + +<p>Agora você pode melhorar a função e talvez enviar alguns alertas. Como por exêmplo mensagens no Telegram quando um dos sites ficar off (status code 404).</p>Azure Data Fundamentals certification with 80% discount2020-06-09T12:30:00-03:002020-06-09T12:30:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-06-09:/en/azure-data-fundamentals-certification-80-discount.html<p>Hey folks, if you want to achieve some certification this year, keep an eye open for vouchers. A few months ago, Oracle released a set of free courses with certifications. Now it's Microsoft time. Microsoft is updating they're certifications and we have a voucher of 80% discount using the coupon …</p><p>Hey folks, if you want to achieve some certification this year, keep an eye open for vouchers. A few months ago, Oracle released a set of free courses with certifications. Now it's Microsoft time. Microsoft is updating they're certifications and we have a voucher of 80% discount using the coupon <strong>DP900Norfolk</strong> at the checkout of the beta certification DP-900. </p> +<p>Be aware that this certification is in beta and the result won't be instantly available as the regular ones. Access the following link and schedule your exam. <a href="https://docs.microsoft.com/pt-br/learn/certifications/exams/dp-900" target="_blank">https://docs.microsoft.com/pt-br/learn/certifications/exams/dp-900</a>.</p> +<p><strong>Update:</strong> There is a 80% voucher also for <a href="https://docs.microsoft.com/en-us/learn/certifications/azure-ai-fundamentals" target="_blank">https://docs.microsoft.com/en-us/learn/certifications/azure-ai-fundamentals</a>. Voucher: <strong>AI900Saratoga</strong></p>Zabbix ICMP pinger processes more than 75%2020-05-25T16:00:00-03:002020-05-25T16:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-05-25:/en/zabbix-icmp-pinger-processes-more-than-75.html<p>So your monitoring sytems have grown and your zabbix started loggin "Zabbix icmp pinger processes more than 75% busy" at the dashboard.</p> +<p><img alt="Dashboard do zabbix avisando sobre o erro" src="/images/zabbix_pinger01.png"></p> +<p>All you have to do is open your config file (<code>/etc/zabbix/zabbix_server.conf</code>) and find the a tag named <code>StartPingers</code>. It'll be commented by default. Uncomment it …</p><p>So your monitoring sytems have grown and your zabbix started loggin "Zabbix icmp pinger processes more than 75% busy" at the dashboard.</p> +<p><img alt="Dashboard do zabbix avisando sobre o erro" src="/images/zabbix_pinger01.png"></p> +<p>All you have to do is open your config file (<code>/etc/zabbix/zabbix_server.conf</code>) and find the a tag named <code>StartPingers</code>. It'll be commented by default. Uncomment it and set it's value to something like 3 or 4. It should solve your problem.</p> +<div class="highlight"><pre><span></span><code><span class="c1">### Option: StartPingers</span> +<span class="c1"># Number of pre-forked instances of ICMP pingers.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 0-1000</span> +<span class="c1"># Default:</span> +<span class="nv">StartPingers</span><span class="o">=</span><span class="m">4</span> +</code></pre></div> + +<h2>How many Pingers do I need?</h2> +<p>Well, there is no exact answer to this. If you set it too high, you'll be wasting resources. The best way to solve, it's increasing them as soon as you notice the percentage growing.</p>Zabbix ICMP pinger processes more than 75%2020-05-25T16:00:00-03:002020-05-25T16:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-05-25:/pt/zabbix-icmp-pinger-processes-more-than-75.html<p>Então o seu systema de monitoramento creasceu e o seu Zabbix começou a printar "<em>Zabbix icmp pinger processes more than 75% busy</em>" no seu dashboard.</p> +<p><img alt="Dashboard do zabbix avisando sobre o erro" src="/images/zabbix_pinger01.png"></p> +<p>Tudo que você tem a fazer é abrir o seu arquivo de configuração (<code>/etc/zabbix/zabbix_server.conf</code>) e localizar a tag chamada <code>StartPingers</code>. Ela deve …</p><p>Então o seu systema de monitoramento creasceu e o seu Zabbix começou a printar "<em>Zabbix icmp pinger processes more than 75% busy</em>" no seu dashboard.</p> +<p><img alt="Dashboard do zabbix avisando sobre o erro" src="/images/zabbix_pinger01.png"></p> +<p>Tudo que você tem a fazer é abrir o seu arquivo de configuração (<code>/etc/zabbix/zabbix_server.conf</code>) e localizar a tag chamada <code>StartPingers</code>. Ela deve estar comentáda por padrão. Descomente a lina e define o seu valor para algo como 3 or 4. Deve resolver seu problema, ao menos até um próximo crescimento do seu monitoramento.</p> +<div class="highlight"><pre><span></span><code><span class="c1">### Option: StartPingers</span> +<span class="c1"># Number of pre-forked instances of ICMP pingers.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 0-1000</span> +<span class="c1"># Default:</span> +<span class="nv">StartPingers</span><span class="o">=</span><span class="m">4</span> +</code></pre></div>Zabbix Server Out of Memory2020-02-27T19:00:00-03:002020-02-27T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-02-27:/en/zabbix-server-out-of-memory-crash.html<p>Do you have a crashing Zabbix Server and looking through the log <code>/var/log/zabbix/zabbix_server.log</code> you see the following out of memory message?</p> +<div class="highlight"><pre><span></span><code>__mem_malloc: skipped <span class="m">0</span> asked <span class="m">24</span> skip_min <span class="m">18446744073709551615</span> skip_max <span class="m">0</span> +<span class="o">[</span>file:dbconfig.c,line:94<span class="o">]</span> __zbx_mem_realloc<span class="o">()</span>: out of memory <span class="o">(</span>requested <span class="m">16</span> bytes<span class="o">)</span> +<span class="o">[</span>file:dbconfig.c,line …</code></pre></div><p>Do you have a crashing Zabbix Server and looking through the log <code>/var/log/zabbix/zabbix_server.log</code> you see the following out of memory message?</p> +<div class="highlight"><pre><span></span><code>__mem_malloc: skipped <span class="m">0</span> asked <span class="m">24</span> skip_min <span class="m">18446744073709551615</span> skip_max <span class="m">0</span> +<span class="o">[</span>file:dbconfig.c,line:94<span class="o">]</span> __zbx_mem_realloc<span class="o">()</span>: out of memory <span class="o">(</span>requested <span class="m">16</span> bytes<span class="o">)</span> +<span class="o">[</span>file:dbconfig.c,line:94<span class="o">]</span> __zbx_mem_realloc<span class="o">()</span>: please increase CacheSize configuration parameter +</code></pre></div> + +<p>Besides the clear solution to the error, that's a common issue on servers that have a few monitoring items on it (servers, switches, firewalls, databases, etc...). To solve, go to your zabbix_server.conf and look for the CacheSize property and set it to a higher value. Its default should be 8M. At a customer that has somewhere between 4 servers, 7 firewalls/appliances, and a few other things, a 32M did the job, but you can set up to 8G.</p> +<p>See ya folks.</p>Zabbix Server Out of Memory2020-02-27T19:00:00-03:002020-02-27T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-02-27:/pt/zabbix-server-out-of-memory-crash.html<p>Você tem um servidor Zabbix crashando e observando o arquivo de log <code>/var/log/zabbix/zabbix_server.log</code> você localiza a seguinte mensagem referênciando falta de memória?</p> +<div class="highlight"><pre><span></span><code>__mem_malloc: skipped <span class="m">0</span> asked <span class="m">24</span> skip_min <span class="m">18446744073709551615</span> skip_max <span class="m">0</span> +<span class="o">[</span>file:dbconfig.c,line:94<span class="o">]</span> __zbx_mem_realloc<span class="o">()</span>: out of memory <span class="o">(</span>requested <span class="m">16</span> bytes<span class="o">)</span> +<span class="o">[</span>file:dbconfig.c …</code></pre></div><p>Você tem um servidor Zabbix crashando e observando o arquivo de log <code>/var/log/zabbix/zabbix_server.log</code> você localiza a seguinte mensagem referênciando falta de memória?</p> +<div class="highlight"><pre><span></span><code>__mem_malloc: skipped <span class="m">0</span> asked <span class="m">24</span> skip_min <span class="m">18446744073709551615</span> skip_max <span class="m">0</span> +<span class="o">[</span>file:dbconfig.c,line:94<span class="o">]</span> __zbx_mem_realloc<span class="o">()</span>: out of memory <span class="o">(</span>requested <span class="m">16</span> bytes<span class="o">)</span> +<span class="o">[</span>file:dbconfig.c,line:94<span class="o">]</span> __zbx_mem_realloc<span class="o">()</span>: please increase CacheSize configuration parameter +</code></pre></div> + +<p>Apesar da simples solução para o erro, isso acaba sendo um problema comum em servidores que tem uma certa quantidade de itens sendo monitorados (servidores, switches, firewalls, bancos, etc...). Para resolver o problema, vá até o ser arquivo <code>zabbix_server.conf</code> e procure pela propriedade <code>CacheSize</code> e sete o seu valor para uma quantidade maior. O seu valor default deve ser algo como 8M. Em clientes que tenham algo como 4 servidores, 7 firewalls/appliances, e algumas outras coisas (bancos, apps), 32M deve resolver o problema, mas você pode setar até algo como 8G (ressalto que mais memória nem sempre é melhor).</p> +<p>Até breve.</p>Flutter + firebase auth crashing2019-10-03T19:00:00-03:002019-10-03T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2019-10-03:/en/flutter_with_firebase_auth_crashing.html<p>Hey Folks, recently I've started learning <a href="https://flutter.dev/">Flutter</a> and right after a TODO List, I tried a Firebase integration. But as soon as I started setting the dependencies, my app stopped opening... just a crash. After a few logs digging, I've found the following log.</p> +<div class="highlight"><pre><span></span><code>AndroidRuntime: FATAL EXCEPTION: main +AndroidRuntime: Process …</code></pre></div><p>Hey Folks, recently I've started learning <a href="https://flutter.dev/">Flutter</a> and right after a TODO List, I tried a Firebase integration. But as soon as I started setting the dependencies, my app stopped opening... just a crash. After a few logs digging, I've found the following log.</p> +<div class="highlight"><pre><span></span><code>AndroidRuntime: FATAL EXCEPTION: main +AndroidRuntime: Process: com.example.diadocasal, PID: <span class="m">13672</span> +AndroidRuntime: java.lang.NoClassDefFoundError: Failed resolution of: Landroid/support/v4/util/ArrayMap<span class="p">;</span> +AndroidRuntime: at com.google.android.gms.internal.measurement.zzca.&lt;clinit&gt;<span class="o">(</span>Unknown Source:60<span class="o">)</span> +AndroidRuntime: at com.google.android.gms.internal.measurement.zzcm.zzr<span class="o">(</span>Unknown Source:7<span class="o">)</span> +AndroidRuntime: at com.google.android.gms.measurement.internal.zzfj.&lt;init&gt;<span class="o">(</span>Unknown Source:23<span class="o">)</span> +</code></pre></div> + +<p>Notice the "NoClassDefFound" of an ArrayMap. To solve that I did the following changes to the files:</p> +<div class="highlight"><pre><span></span><code><span class="c1">//build.gradle file</span> + <span class="n">ext</span><span class="p">.</span><span class="na">kotlin_version</span> <span class="o">=</span> <span class="err">&#39;</span><span class="mf">1.3.20</span><span class="err">&#39;</span> +<span class="o">[</span><span class="p">...</span><span class="o">]</span> + <span class="n">dependencies</span> <span class="p">{</span> + <span class="n">classpath</span> <span class="err">&#39;</span><span class="n">com</span><span class="p">.</span><span class="na">android</span><span class="p">.</span><span class="na">tools</span><span class="p">.</span><span class="na">build</span><span class="p">:</span><span class="n">gradle</span><span class="p">:</span><span class="mf">3.3.0</span><span class="err">&#39;</span> <span class="c1">// gradle version</span> +</code></pre></div> + +<div class="highlight"><pre><span></span><code><span class="c1">;gradle.properties file</span> +<span class="na">org.gradle.jvmargs</span><span class="o">=</span><span class="s">-Xmx1536M ;mine have just this line at first</span> +<span class="na">android.useAndroidX</span><span class="o">=</span><span class="s">true ; uses androidX instead of the default support library</span> +<span class="na">android.enableJetifier</span><span class="o">=</span><span class="s">true ; uses jetpack libraries</span> +<span class="na">android.enableR8</span><span class="o">=</span><span class="s">true ; the new code shriker</span> +</code></pre></div> + +<p>After that, voilà, app up and running.</p>Removing a user from SQL Server database who owns a schema2019-09-06T07:00:00-03:002020-10-21T18:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2019-09-06:/en/removing-user-from-sql-server-database.html<p>Your customer urge you to drop a user from the MsSQL Server database, but you stuck with the following related error:</p> +<div class="highlight"><pre><span></span><code><span class="n">Error</span><span class="o">:</span> <span class="mi">15138</span> <span class="n">The</span> <span class="n">database</span> <span class="n">principal</span> <span class="n">owns</span> <span class="n">a</span> <span class="n">schema</span> <span class="k">in</span> <span class="n">the</span> <span class="n">database</span><span class="o">,</span> <span class="n">and</span> <span class="n">cannot</span> <span class="n">be</span> <span class="n">dropped</span><span class="o">.</span> +</code></pre></div> + +<p>That means that the user owns one or more shcemas of your database. If …</p><p>Your customer urge you to drop a user from the MsSQL Server database, but you stuck with the following related error:</p> +<div class="highlight"><pre><span></span><code><span class="n">Error</span><span class="o">:</span> <span class="mi">15138</span> <span class="n">The</span> <span class="n">database</span> <span class="n">principal</span> <span class="n">owns</span> <span class="n">a</span> <span class="n">schema</span> <span class="k">in</span> <span class="n">the</span> <span class="n">database</span><span class="o">,</span> <span class="n">and</span> <span class="n">cannot</span> <span class="n">be</span> <span class="n">dropped</span><span class="o">.</span> +</code></pre></div> + +<p>That means that the user owns one or more shcemas of your database. If you don't have access to the SSMS to see which schema or objects the user owns, the following SQL should do the job.</p> +<div class="highlight"><pre><span></span><code><span class="k">USE</span><span class="w"> </span><span class="o">[</span><span class="n">DATABASENAME</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> + +<span class="k">select</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Objeto</span><span class="p">,</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Owner</span><span class="w"></span> +<span class="k">from</span><span class="w"> </span><span class="n">sys</span><span class="p">.</span><span class="n">schemas</span><span class="w"> </span><span class="n">so</span><span class="w"></span> +<span class="k">inner</span><span class="w"> </span><span class="k">join</span><span class="w"> </span><span class="n">sysusers</span><span class="w"> </span><span class="n">su</span><span class="w"> </span><span class="k">on</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">principal_id</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">uid</span><span class="w"></span> +<span class="k">where</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">&#39;username&#39;</span><span class="w"></span> + +<span class="k">select</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Objeto</span><span class="p">,</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Owner</span><span class="p">,</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">xtype</span><span class="w"> </span><span class="n">Tipo</span><span class="w"></span> +<span class="k">from</span><span class="w"> </span><span class="n">sys</span><span class="p">.</span><span class="n">sysobjects</span><span class="w"> </span><span class="n">so</span><span class="w"></span> +<span class="k">inner</span><span class="w"> </span><span class="k">join</span><span class="w"> </span><span class="n">sysusers</span><span class="w"> </span><span class="n">su</span><span class="w"> </span><span class="k">on</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">uid</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">uid</span><span class="w"></span> +<span class="k">where</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">&#39;username&#39;</span><span class="w"></span> +</code></pre></div> + +<p>Once you have the objects/schemas owned by the user, you can change them with the following SQL (schema change sample):</p> +<div class="highlight"><pre><span></span><code><span class="k">USE</span><span class="w"> </span><span class="o">[</span><span class="n">DATABASENAME</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +<span class="k">ALTER</span><span class="w"> </span><span class="k">AUTHORIZATION</span><span class="w"> </span><span class="k">ON</span><span class="w"> </span><span class="k">SCHEMA</span><span class="o">::[</span><span class="n">db_datareader</span><span class="o">]</span><span class="w"> </span><span class="k">TO</span><span class="w"> </span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="w"> </span><span class="c1">-- new owner username</span> +<span class="k">ALTER</span><span class="w"> </span><span class="k">AUTHORIZATION</span><span class="w"> </span><span class="k">ON</span><span class="w"> </span><span class="k">SCHEMA</span><span class="o">::[</span><span class="n">db_datawriter</span><span class="o">]</span><span class="w"> </span><span class="k">TO</span><span class="w"> </span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +</code></pre></div> + +<p>Then you're ready to drop the user <code>DROP USER [username]</code></p> +<h2>How to list all the schemas and it's owners?</h2> +<p>Here's a script to list schemas and it's owners.</p> +<div class="highlight"><pre><span></span><code><span class="k">USE</span><span class="w"> </span><span class="o">[</span><span class="n">DATABASENAME</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +<span class="k">SELECT</span><span class="w"></span> +<span class="w"> </span><span class="nf">schema_name</span><span class="p">(</span><span class="nf">schema_id</span><span class="p">)</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="n">schemaname</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="nf">user_name</span><span class="p">(</span><span class="n">schm</span><span class="p">.</span><span class="n">principal_id</span><span class="p">)</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="n">username</span><span class="p">,</span><span class="w"> </span><span class="o">*</span><span class="w"></span> +<span class="k">FROM</span><span class="w"> </span><span class="n">sys</span><span class="p">.</span><span class="n">schemas</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="n">schm</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +</code></pre></div>Removendo um usuário de uma base SQL Server2019-09-06T07:00:00-03:002020-10-21T18:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2019-09-06:/pt/removing-user-from-sql-server-database.html<p>O seu cliente lhe pede com urgência para <em>dropar</em> um usuário da sua base MsSQL Server, mas você trava com o seguinte aviso de erro:</p> +<div class="highlight"><pre><span></span><code><span class="n">Error</span><span class="o">:</span> <span class="mi">15138</span> <span class="n">The</span> <span class="n">database</span> <span class="n">principal</span> <span class="n">owns</span> <span class="n">a</span> <span class="n">schema</span> <span class="k">in</span> <span class="n">the</span> <span class="n">database</span><span class="o">,</span> <span class="n">and</span> <span class="n">cannot</span> <span class="n">be</span> <span class="n">dropped</span><span class="o">.</span> +</code></pre></div> + +<p>Se você não possui (ou no momento não consegue acesso …</p><p>O seu cliente lhe pede com urgência para <em>dropar</em> um usuário da sua base MsSQL Server, mas você trava com o seguinte aviso de erro:</p> +<div class="highlight"><pre><span></span><code><span class="n">Error</span><span class="o">:</span> <span class="mi">15138</span> <span class="n">The</span> <span class="n">database</span> <span class="n">principal</span> <span class="n">owns</span> <span class="n">a</span> <span class="n">schema</span> <span class="k">in</span> <span class="n">the</span> <span class="n">database</span><span class="o">,</span> <span class="n">and</span> <span class="n">cannot</span> <span class="n">be</span> <span class="n">dropped</span><span class="o">.</span> +</code></pre></div> + +<p>Se você não possui (ou no momento não consegue acesso) ao SSMS (SQL Server Management Studio) para verificar quais schemas ou objetos o usuário é "dono", a seguinte SQL vai resolver o problema.</p> +<div class="highlight"><pre><span></span><code><span class="k">USE</span><span class="w"> </span><span class="o">[</span><span class="n">DATABASENAME</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> + +<span class="k">select</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Objeto</span><span class="p">,</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Owner</span><span class="w"></span> +<span class="k">from</span><span class="w"> </span><span class="n">sys</span><span class="p">.</span><span class="n">schemas</span><span class="w"> </span><span class="n">so</span><span class="w"></span> +<span class="k">inner</span><span class="w"> </span><span class="k">join</span><span class="w"> </span><span class="n">sysusers</span><span class="w"> </span><span class="n">su</span><span class="w"> </span><span class="k">on</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">principal_id</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">uid</span><span class="w"></span> +<span class="k">where</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">&#39;username&#39;</span><span class="w"></span> + +<span class="k">select</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Objeto</span><span class="p">,</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Owner</span><span class="p">,</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">xtype</span><span class="w"> </span><span class="n">Tipo</span><span class="w"></span> +<span class="k">from</span><span class="w"> </span><span class="n">sys</span><span class="p">.</span><span class="n">sysobjects</span><span class="w"> </span><span class="n">so</span><span class="w"></span> +<span class="k">inner</span><span class="w"> </span><span class="k">join</span><span class="w"> </span><span class="n">sysusers</span><span class="w"> </span><span class="n">su</span><span class="w"> </span><span class="k">on</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">uid</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">uid</span><span class="w"></span> +<span class="k">where</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">&#39;username&#39;</span><span class="w"></span> +</code></pre></div> + +<p>Assim que você tiver os objetos/schemas que o usuário é dono, você pode alterar os mesmos com a seguinte SQL (exemplo de troca de schema):</p> +<div class="highlight"><pre><span></span><code><span class="k">USE</span><span class="w"> </span><span class="o">[</span><span class="n">DATABASENAME</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +<span class="k">ALTER</span><span class="w"> </span><span class="k">AUTHORIZATION</span><span class="w"> </span><span class="k">ON</span><span class="w"> </span><span class="k">SCHEMA</span><span class="o">::[</span><span class="n">db_datareader</span><span class="o">]</span><span class="w"> </span><span class="k">TO</span><span class="w"> </span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="w"> </span><span class="c1">-- username do novo dono</span> +<span class="k">ALTER</span><span class="w"> </span><span class="k">AUTHORIZATION</span><span class="w"> </span><span class="k">ON</span><span class="w"> </span><span class="k">SCHEMA</span><span class="o">::[</span><span class="n">db_datawriter</span><span class="o">]</span><span class="w"> </span><span class="k">TO</span><span class="w"> </span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +</code></pre></div> + +<p>Então, você pode dropar o usuário <code>DROP USER [username]</code>.</p>Limiting Connection Resources on SQL Server2019-08-12T12:00:00-03:002019-08-12T12:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2019-08-12:/en/limiting-connection-resources-sql-server.html<p>Have you ever suffered from a slow SQLServer database? Someone love to run that heavy query in the database? Resource Governor to the rescue. You can set a few rules on how users (connections actually) will use the server/database resources based on a few things.</p> +<p>First things first, if …</p><p>Have you ever suffered from a slow SQLServer database? Someone love to run that heavy query in the database? Resource Governor to the rescue. You can set a few rules on how users (connections actually) will use the server/database resources based on a few things.</p> +<p>First things first, if you don't have DAC enabled, enable it now. Dealing with resource governor can lock you out of the database and leave you without action (almost... you can start the server with -c -m -f).</p> +<p>Now to understand how Resource Governor works, we have a few keywords <code>resource pool</code>, <code>workload group</code> e <code>Classifier Function</code>.</p> +<p><img alt="Pool Sample" src="/images/sql-pool.png"></p> +<h2>Resource Pool</h2> +<p>First, we have the Resource Pool, with is the bigger resource group that we have the ability to manage. With it, we can set a few things like: <code>MIN_CPU_PERCENT</code>, <code>MAX_CPU_PERCENT</code>, <code>MIN_MEMORY_PERCENT</code>, <code>MAX_MEMORY_PERCENT</code>, <code>MIN_IOPS_PER_VOLUME</code>, and <code>MAX_IOPS_PER_VOLUME</code>.</p> +<p>Be aware that the <code>MAX_CPU_PERCENT</code> will just "works" when there is another connection with a higher priority, otherwise it will use what is available. Let's create a pool.</p> +<div class="highlight"><pre><span></span><code><span class="k">CREATE</span><span class="w"> </span><span class="n">RESOURCE</span><span class="w"> </span><span class="n">POOL</span><span class="w"> </span><span class="o">[</span><span class="n">SpreadSheet</span><span class="o">]</span><span class="w"></span> +<span class="k">WITH</span><span class="w"> </span><span class="p">(</span><span class="w"></span> +<span class="w"> </span><span class="n">MIN_CPU_PERCENT</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">MAX_CPU_PERCENT</span><span class="o">=</span><span class="mi">20</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">MIN_MEMORY_PERCENT</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">MAX_MEMORY_PERCENT</span><span class="o">=</span><span class="mi">20</span><span class="w"></span> +<span class="p">);</span><span class="w"></span> +</code></pre></div> + +<p>## Workload Group</p> +<p>Then we have a workload group that "works" inside a pool, so you can have another granularity on how you can split your resources. Again, we have a few options: <code>IMPORTANCE</code>, <code>REQUEST_MAX_CPU_TIME_SEC</code>, <code>REQUEST_MAX_MEMORY_GRANT_PERCENT</code>, <code>GROUP_MAX_REQUESTS</code>.</p> +<p>The <code>IMPORTANCE</code> set guesses what... the importance of that workload inside the pool, you can set LOW, MEDIUM, HIGH. GROUP_MAX_REQUESTS sets how many requests can run at the same time inside that workload (0 will set as NO LIMIT)</p> +<div class="highlight"><pre><span></span><code><span class="k">CREATE</span><span class="w"> </span><span class="n">WORKLOAD</span><span class="w"> </span><span class="k">GROUP</span><span class="w"> </span><span class="o">[</span><span class="n">DepartmentA</span><span class="o">]</span><span class="w"> </span> +<span class="k">WITH</span><span class="w"> </span><span class="p">(</span><span class="w"></span> +<span class="w"> </span><span class="n">GROUP_MAX_REQUESTS</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">IMPORTANCE</span><span class="o">=</span><span class="n">LOW</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">REQUEST_MAX_CPU_TIME_SEC</span><span class="o">=</span><span class="mi">10</span><span class="p">,</span><span class="w"> </span><span class="c1">-- Time running/using CPU</span> +<span class="w"> </span><span class="n">REQUEST_MAX_MEMORY_GRANT_PERCENT</span><span class="o">=</span><span class="mi">15</span><span class="w"></span> +<span class="p">)</span><span class="w"> </span><span class="k">USING</span><span class="w"> </span><span class="o">[</span><span class="n">SpreadSheet</span><span class="o">]</span><span class="p">;</span><span class="w"> </span><span class="c1">-- pool name here</span> +</code></pre></div> + +<h2>Classifier Function</h2> +<p>This is where everything begins... This is the entry point where you should set the group name. It's a function that will run for every new connection so be aware that if your function runs lots of queries or some heavy stuff... that time will be added to the connection handshake. If the function returns NULL or a group name that doesn't exist, the 'default' group will be used... Yes, there is a default workload group where everything runs where there's no classifier.</p> +<div class="highlight"><pre><span></span><code><span class="k">CREATE</span><span class="w"> </span><span class="k">FUNCTION</span><span class="w"> </span><span class="n">fnClassWorkloadGovernor</span><span class="p">()</span><span class="w"> </span> +<span class="k">RETURNS</span><span class="w"> </span><span class="n">SYSNAME</span><span class="w"> </span><span class="k">WITH</span><span class="w"> </span><span class="n">SCHEMABINDING</span><span class="w"> </span> +<span class="k">AS</span><span class="w"> </span> +<span class="k">BEGIN</span><span class="w"> </span> +<span class="w"> </span><span class="k">IF</span><span class="w"> </span><span class="nf">APP_NAME</span><span class="p">()</span><span class="w"> </span><span class="ow">LIKE</span><span class="w"> </span><span class="s1">&#39;%Excel%&#39;</span><span class="w"></span> +<span class="w"> </span><span class="k">RETURN</span><span class="w"> </span><span class="s1">&#39;DepartmentA&#39;</span><span class="w"></span> + +<span class="w"> </span><span class="k">IF</span><span class="w"> </span><span class="nf">HOST_NAME</span><span class="p">()</span><span class="w"> </span><span class="ow">LIKE</span><span class="w"> </span><span class="s1">&#39;%THAT_MACHINE_OR_APP_SERVER%&#39;</span><span class="w"></span> +<span class="w"> </span><span class="k">RETURN</span><span class="w"> </span><span class="s1">&#39;LowPriority&#39;</span><span class="w"></span> + +<span class="w"> </span><span class="k">RETURN</span><span class="w"> </span><span class="k">NULL</span><span class="w"></span> +<span class="k">END</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> + +<span class="k">ALTER</span><span class="w"> </span><span class="n">RESOURCE</span><span class="w"> </span><span class="n">GOVERNOR</span><span class="w"> </span><span class="k">WITH</span><span class="w"> </span><span class="p">(</span><span class="n">CLASSIFIER_FUNCTION</span><span class="o">=</span><span class="n">dbo</span><span class="p">.</span><span class="n">fnClassWorkloadGovernor</span><span class="p">);</span><span class="w"></span> +<span class="k">ALTER</span><span class="w"> </span><span class="n">RESOURCE</span><span class="w"> </span><span class="n">GOVERNOR</span><span class="w"> </span><span class="k">RECONFIGURE</span><span class="p">;</span><span class="w"></span> +</code></pre></div> + +<p>There you go... now you have a fully working resource governor, but look out that If you want to delete that classifier function, first you have to remove it from the resource governor (look the SCHEMABINDING at the create up there).</p> +<p>To disable Resource Governor</p> +<div class="highlight"><pre><span></span><code><span class="k">ALTER</span><span class="w"> </span><span class="n">RESOURCE</span><span class="w"> </span><span class="n">GOVERNOR</span><span class="w"> </span><span class="k">WITH</span><span class="w"> </span><span class="p">(</span><span class="n">CLASSIFIER_FUNCTION</span><span class="o">=</span><span class="k">null</span><span class="p">)</span><span class="w"></span> +<span class="k">ALTER</span><span class="w"> </span><span class="n">RESOURCE</span><span class="w"> </span><span class="n">GOVERNOR</span><span class="w"> </span><span class="k">RECONFIGURE</span><span class="w"></span> + +<span class="k">ALTER</span><span class="w"> </span><span class="n">RESOURCE</span><span class="w"> </span><span class="n">GOVERNOR</span><span class="w"> </span><span class="n">DISABLE</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +</code></pre></div>Using git hooks to easy your life2019-07-30T20:00:00-03:002019-07-30T20:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2019-07-30:/en/using_git_hooks_easy_your_life.html<p>Hey folks, it's been a time since my last post. In the meantime, I moved to another state, changed job, and started learning new kinds of stuff. Today I would like to share one thing that I usually do with my small git projects. Git has many cool features, git …</p><p>Hey folks, it's been a time since my last post. In the meantime, I moved to another state, changed job, and started learning new kinds of stuff. Today I would like to share one thing that I usually do with my small git projects. Git has many cool features, git hooks were one of them. I'll talk about the pre-commit hook today.</p> +<p>Let's say that, for some reason, you don't have a CI tool/server running after every commit and you want to enforce that every developer runs the tests before every commit? Git pre-commit to the rescue. You can code the hooks with shell, ruby, python, and I could be wrong, but even PHP would work. pre-commit is a client-side hook (we have server side too) and he's located inside the <cite>.git/hooks</cite> folder. Let's jump to the code... Create a file called 'pre-commit' inside that folder with the following code.</p> +<div class="highlight"><pre><span></span><span class="ch">#!/bin/bash</span> +npm <span class="nb">test</span> <span class="c1"># assuming you&#39;re using it inside a nodeJS project</span> +</pre></div> +<p>Don't forget to make the script executable!! Now break your test and try to commit. That's easy but can save you from breaking the tests at the main CI/Travis/Codeship/etc and being notified by email :). Why not even validate the lint of your project or check if the coverage doesn't fall? Does your team/company have a patter for commit messages? No problem, there is a hook called <cite>commit-msg</cite> that you can use to validate your message.</p> +Microservices with NodeJS, Express.js and RabbitMQ Part 22018-04-13T13:00:00-03:002018-04-13T13:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-04-13:/en/microservices_nodejs_express_rabbitmq_part_2.html<p>If you haven't read the <a class="reference external" href="https://www.sipmann.com/microservices_nodejs_express_rabbitmq_part_1-en.html">part 1</a> go ahead and read it... It can be useful :). Or if for some reason you want to start now, you can grab the project where we stopped <a class="reference external" href="https://github.com/sipmann/imagecompacter/releases/tag/v1">here</a> and get along. On this part, we'll implement the RabbitMQ queue and see how we …</p><p>If you haven't read the <a class="reference external" href="https://www.sipmann.com/microservices_nodejs_express_rabbitmq_part_1-en.html">part 1</a> go ahead and read it... It can be useful :). Or if for some reason you want to start now, you can grab the project where we stopped <a class="reference external" href="https://github.com/sipmann/imagecompacter/releases/tag/v1">here</a> and get along. On this part, we'll implement the RabbitMQ queue and see how we can get the best of our app and server with that.</p> +<p>Before we began coding, let's understand why we are going to use RabbitMQ if what we have now works? If you check again, you'll see how long it takes to answer the request with the optimized image. It takes a few seconds, so imagine an online service with thousands of request to optimize images (like <a class="reference external" href="https://tinypng.com/">TinyPNG</a>) how long is it gonna take to answer every request? How much of your server is it gonna take? With only one service running, probably the server will crash.</p> +<p>With a queue, we can schedule the requests so we can use the amount of memory and processor that our server has, without taking more than we can. It's better to take a few seconds to answer the request then throw some error to the user. Want more? With RabbitMQ we can see how the queue is doing and we can add more consumers (workers) to it and get things done quicker and distribute the job.</p> +<p>First of all, we need an up and running Rabbit server, for the sake of simplicity, I'll use a Docker container with it inside.</p> +<div class="highlight"><pre><span></span>docker run -d --name rabbit -p <span class="m">5672</span>:5672 -p <span class="m">8080</span>:15672 rabbitmq:3-management +</pre></div> +<p>You can see that we're running the rabbitmq:3-management image, which provides us a web interface to see how things are going. After that, if you look at our code you'll see that all the job is made at the '/upload' route, and that's what we'll change.</p> +<p>First, we need to understand what we need from RabbitMQ. We need something that, we send an image to a queue and get an optimized image back from that. There is a name for that, is RPC (remote procedure call) and there are two ways of doing this with rabbit. Both the ways you can see on their tutorial page. We'll use the approach that uses a global channel whose id is randomly generated (you'll use the name 'amq.rabbitmq.reply-to' but the rabbit will do the job).</p> +<p>Let's start importing the library, defining a few variables and defining a init function that will establish a connection with the rabbit server and create our RPC queue. The RPC queue it's where we'll receive the answer from the consumer (our worker).</p> +<div class="highlight"><pre><span></span><span class="c1">//import the library</span> +<span class="kr">const</span> <span class="nx">amqplib</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;amqplib&#39;</span><span class="p">);</span> + +<span class="c1">//queue channel</span> +<span class="kd">let</span> <span class="nx">channel</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span> +<span class="c1">//queue name</span> +<span class="kr">const</span> <span class="nx">QUEUE</span> <span class="o">=</span> <span class="s1">&#39;optimizeimg&#39;</span><span class="p">;</span> + +<span class="c1">//...</span> + +<span class="kd">function</span> <span class="nx">init</span><span class="p">()</span> <span class="p">{</span> + <span class="k">return</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;amqplib&#39;</span><span class="p">).</span><span class="nx">connect</span><span class="p">(</span><span class="s1">&#39;amqp://localhost&#39;</span><span class="p">)</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">conn</span> <span class="p">=&gt;</span> <span class="nx">conn</span><span class="p">.</span><span class="nx">createChannel</span><span class="p">())</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">ch</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="nx">channel</span> <span class="o">=</span> <span class="nx">ch</span><span class="p">;</span> + + <span class="c1">//this queue is a &quot;Direct reply-to&quot; read more at the docs</span> + <span class="c1">//When some msg comes in, we &quot;emit&quot; a message to the proper &quot;correlationId&quot; listener</span> + <span class="nx">ch</span><span class="p">.</span><span class="nx">consume</span><span class="p">(</span><span class="s1">&#39;amq.rabbitmq.reply-to&#39;</span><span class="p">,</span> <span class="nx">msg</span> <span class="p">=&gt;</span> <span class="nx">eventEmitter</span><span class="p">.</span><span class="nx">emit</span><span class="p">(</span><span class="nx">msg</span><span class="p">.</span><span class="nx">properties</span><span class="p">.</span><span class="nx">correlationId</span><span class="p">,</span> <span class="nx">msg</span><span class="p">.</span><span class="nx">content</span><span class="p">),</span> <span class="p">{</span><span class="nx">noAck</span><span class="o">:</span> <span class="kc">true</span><span class="p">});</span> + <span class="p">});</span> +<span class="p">}</span> + +<span class="c1">//Random id generator</span> +<span class="kd">function</span> <span class="nx">randomid</span><span class="p">()</span> <span class="p">{</span> + <span class="k">return</span> <span class="k">new</span> <span class="nb">Date</span><span class="p">().</span><span class="nx">getTime</span><span class="p">().</span><span class="nx">toString</span><span class="p">()</span> <span class="o">+</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">random</span><span class="p">().</span><span class="nx">toString</span><span class="p">()</span> <span class="o">+</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">random</span><span class="p">().</span><span class="nx">toString</span><span class="p">();</span> +<span class="p">}</span> + +<span class="nx">app</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="s1">&#39;/upload&#39;</span><span class="p">,</span> <span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="kd">let</span> <span class="nx">img</span> <span class="o">=</span> <span class="nx">req</span><span class="p">.</span><span class="nx">files</span><span class="p">.</span><span class="nx">image</span><span class="p">;</span> + + <span class="kd">let</span> <span class="nx">id</span> <span class="o">=</span> <span class="nx">randomid</span><span class="p">();</span> + + <span class="c1">//Event listener that will fire when the proper randomid is provided</span> + <span class="nx">eventEmitter</span><span class="p">.</span><span class="nx">once</span><span class="p">(</span><span class="nx">id</span><span class="p">,</span> <span class="nx">msg</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="nx">res</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="nx">msg</span><span class="p">,</span> <span class="s1">&#39;binary&#39;</span><span class="p">);</span> + <span class="nx">res</span><span class="p">.</span><span class="nx">end</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="s1">&#39;binary&#39;</span><span class="p">);</span> + <span class="p">});</span> + + <span class="c1">//Checks if the queue exists, and create it if needed.</span> + <span class="nx">channel</span><span class="p">.</span><span class="nx">assertQueue</span><span class="p">(</span><span class="nx">QUEUE</span><span class="p">)</span> + <span class="c1">//Sent the buffered img to the queue with the ID and the responseQueue</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="nx">channel</span><span class="p">.</span><span class="nx">sendToQueue</span><span class="p">(</span><span class="nx">QUEUE</span><span class="p">,</span> <span class="nx">img</span><span class="p">.</span><span class="nx">data</span><span class="p">,</span> <span class="p">{</span><span class="nx">correlationId</span><span class="o">:</span><span class="nx">id</span><span class="p">,</span> <span class="nx">replyTo</span><span class="o">:</span> <span class="s1">&#39;amq.rabbitmq.reply-to&#39;</span><span class="p">}));</span> + +<span class="p">});</span> + +<span class="c1">//Finally start the app with the given port number</span> +<span class="c1">//now we initialize the rabbitmq connection before start the server</span> +<span class="nx">init</span><span class="p">()</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="nx">app</span><span class="p">.</span><span class="nx">listen</span><span class="p">(</span><span class="mi">4000</span><span class="p">,</span> <span class="p">()</span> <span class="p">=&gt;</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;Example app listening on port 4000!&#39;</span><span class="p">)))</span> + <span class="p">.</span><span class="k">catch</span><span class="p">(</span><span class="nx">err</span><span class="p">=&gt;</span><span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="nx">err</span><span class="p">));</span> +</pre></div> +<p>Ok, now we have our server code rewritten so let's see our worker code. Create a file named 'worker.js' and let's see how it's gonna be. It's really simple. You initialize a connection with RabbitMQ too, create a channel, check if the queue exists and start watching for incoming messages. When an image arrives, we do the job with it and send back to the &quot;replyTo&quot; queue the optimized image for the proper sender (correlationId). In the end, we do an acknowledge of the message so it get's out from the queue.</p> +<div class="highlight"><pre><span></span><span class="kr">const</span> <span class="nx">imagemin</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;imagemin&#39;</span><span class="p">);</span> +<span class="kr">const</span> <span class="nx">imageminPngquant</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;imagemin-pngquant&#39;</span><span class="p">);</span> + +<span class="kd">let</span> <span class="nx">channel</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span> +<span class="kr">const</span> <span class="nx">QUEUE</span> <span class="o">=</span> <span class="s1">&#39;imgqueue&#39;</span><span class="p">;</span> + +<span class="nx">require</span><span class="p">(</span><span class="s1">&#39;amqplib&#39;</span><span class="p">).</span><span class="nx">connect</span><span class="p">(</span><span class="s1">&#39;amqp://localhost&#39;</span><span class="p">)</span> +<span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">conn</span> <span class="p">=&gt;</span><span class="nx">conn</span><span class="p">.</span><span class="nx">createChannel</span><span class="p">())</span> +<span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">ch</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="nx">ch</span><span class="p">.</span><span class="nx">assertQueue</span><span class="p">(</span><span class="nx">QUEUE</span><span class="p">)</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="c1">//Watch incomming messages</span> + <span class="nx">ch</span><span class="p">.</span><span class="nx">consume</span><span class="p">(</span><span class="nx">QUEUE</span><span class="p">,</span> <span class="nx">msg</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="nx">imagemin</span><span class="p">.</span><span class="nx">buffer</span><span class="p">(</span><span class="nx">msg</span><span class="p">.</span><span class="nx">content</span><span class="p">,</span> <span class="p">{</span> + <span class="nx">plugins</span><span class="o">:</span> <span class="p">[</span><span class="nx">imageminPngquant</span><span class="p">()]</span> + <span class="p">})</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">out</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="c1">//Send back to the sender (replyTo) queue and give the correlationId back</span> + <span class="c1">//so we can emit the event.</span> + <span class="nx">ch</span><span class="p">.</span><span class="nx">sendToQueue</span><span class="p">(</span><span class="nx">msg</span><span class="p">.</span><span class="nx">properties</span><span class="p">.</span><span class="nx">replyTo</span><span class="p">,</span> <span class="nx">out</span><span class="p">,</span> <span class="p">{</span> + <span class="nx">correlationId</span><span class="o">:</span> <span class="nx">msg</span><span class="p">.</span><span class="nx">properties</span><span class="p">.</span><span class="nx">correlationId</span> + <span class="p">});</span> + + <span class="c1">//Acknowledge the job done with the message.</span> + <span class="nx">ch</span><span class="p">.</span><span class="nx">ack</span><span class="p">(</span><span class="nx">msg</span><span class="p">);</span> + <span class="p">});</span> + <span class="p">});</span> + <span class="p">});</span> +<span class="p">});</span> +</pre></div> +<p>The key points here are. Open just one connection to the hole server. You CAN create one channel for every request that you receive, but it can take some time if you have a really big cluster of RabbitMQ. It was a quick tutorial, but I hope that it was able to clear a few questions that you might have when working with rabbit and express.</p> +Microservices with NodeJS, Express.js and RabbitMQ Part 12018-04-04T11:25:00-03:002018-04-04T11:25:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-04-04:/en/microservices_nodejs_express_rabbitmq_part_1.html<p>This is the first part of a microservices development series. The service will consist of the bellow architecture, where we will expose an image optimizer service that will forward the request to a <a class="reference external" href="https://www.rabbitmq.com/">RabbitMQ</a> queue and answer with the bytecode of the optimized image. It shouldn't be a long series …</p><p>This is the first part of a microservices development series. The service will consist of the bellow architecture, where we will expose an image optimizer service that will forward the request to a <a class="reference external" href="https://www.rabbitmq.com/">RabbitMQ</a> queue and answer with the bytecode of the optimized image. It shouldn't be a long series so let's see what we can do.</p> +<img alt="Service architecture" src="/images/microservices_rabit_pt1.png" /> +<p>Let's get our environment working. First, we'll need to install the libraries that we'll use.</p> +<p>Create a dir and initialize the nodejs application inside it (<cite>npm init</cite>) and then let's install the deps.</p> +<ul class="simple"> +<li>amqplib - AMQP lib to interact with rabbitmq</li> +<li>express - Do our basic rest API</li> +<li>express-fileupload - easy file upload parser</li> +<li>imagemin and imagemin-pngquant - our image compacter</li> +</ul> +<div class="highlight"><pre><span></span>npm install --save express amqplib express-fileupload imagemin imagemin-pngquant +</pre></div> +<p>Now let's write the entry points for our service, we'll have two basic entry points. The path <cite>/</cite> that will have a welcome message, the second path will be <cite>/upload</cite> and this is the one that will handle the image and produce a job for our workers.</p> +<div class="highlight"><pre><span></span><span class="kr">const</span> <span class="nx">express</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;express&#39;</span><span class="p">);</span> +<span class="kr">const</span> <span class="nx">fileUpload</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;express-fileupload&#39;</span><span class="p">);</span> + +<span class="c1">//Instantiate the app and set the fileupload parser to manage files</span> +<span class="kr">const</span> <span class="nx">app</span> <span class="o">=</span> <span class="nx">express</span><span class="p">();</span> +<span class="nx">app</span><span class="p">.</span><span class="nx">use</span><span class="p">(</span><span class="nx">fileUpload</span><span class="p">());</span> + +<span class="c1">//Our index entry point</span> +<span class="nx">app</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;/&#39;</span><span class="p">,</span> <span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="nx">res</span><span class="p">.</span><span class="nx">send</span><span class="p">(</span><span class="s1">&#39;Hello From ImageCompacter service&#39;</span><span class="p">));</span> + +<span class="c1">//The path that will handle the image file and throw them to the queue</span> +<span class="nx">app</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="s1">&#39;/upload&#39;</span><span class="p">,</span> <span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="c1">//With express-fileupload we can grab the files like this</span> + <span class="kd">let</span> <span class="nx">img</span> <span class="o">=</span> <span class="nx">req</span><span class="p">.</span><span class="nx">files</span><span class="p">.</span><span class="nx">image</span><span class="p">;</span> <span class="c1">//&quot;image&quot; is the name of the input</span> + + <span class="nx">res</span><span class="p">.</span><span class="nx">send</span><span class="p">(</span><span class="s1">&#39;Not ready yet&#39;</span><span class="p">);</span> +<span class="p">});</span> + +<span class="c1">//Finally start the app with the given port number</span> +<span class="nx">app</span><span class="p">.</span><span class="nx">listen</span><span class="p">(</span><span class="mi">4000</span><span class="p">,</span> <span class="p">()</span> <span class="p">=&gt;</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;Example app listening on port 4000!&#39;</span><span class="p">));</span> +</pre></div> +<p>Let's check if it works, run the service with node.</p> +<div class="highlight"><pre><span></span>node index.js +Example app listening on port <span class="m">4000</span>! +</pre></div> +<p>Open the browser and check if it prints our hello message when accessing <cite>localhost:4000</cite>. Works? Greate. Now let's work with the image and see how we do it. To optimize our image, we'll use the library imagemin and <a class="reference external" href="https://www.npmjs.com/package/imagemin-pngquant">imagemin-pngquant</a>, it will be that simple for now, we'll work with rabbitmq latter.</p> +<div class="highlight"><pre><span></span><span class="kr">const</span> <span class="nx">imagemin</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;imagemin&#39;</span><span class="p">);</span> +<span class="kr">const</span> <span class="nx">imageminPngquant</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;imagemin-pngquant&#39;</span><span class="p">);</span> +<span class="c1">//...</span> + +<span class="c1">//The path that will handle the image file and throw them to the queue</span> +<span class="nx">app</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="s1">&#39;/upload&#39;</span><span class="p">,</span> <span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="kd">let</span> <span class="nx">img</span> <span class="o">=</span> <span class="nx">req</span><span class="p">.</span><span class="nx">files</span><span class="p">.</span><span class="nx">image</span><span class="p">;</span> <span class="c1">//&quot;image&quot; is the name of the input</span> + + <span class="nx">imagemin</span><span class="p">.</span><span class="nx">buffer</span><span class="p">(</span><span class="nx">img</span><span class="p">.</span><span class="nx">data</span><span class="p">,</span> <span class="p">{</span> + <span class="nx">plugins</span><span class="o">:</span> <span class="p">[</span><span class="nx">imageminPngquant</span><span class="p">()]</span> + <span class="p">})</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">out</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="nx">res</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="nx">out</span><span class="p">,</span><span class="s1">&#39;binary&#39;</span><span class="p">);</span> + <span class="nx">res</span><span class="p">.</span><span class="nx">end</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="s1">&#39;binary&#39;</span><span class="p">);</span> + <span class="p">});</span> +<span class="p">});</span> + + <span class="c1">//...</span> +</pre></div> +<p>Use <a class="reference external" href="https://www.getpostman.com/">Postman</a> to test the request. To see if it will work, make a request to <cite>http://localhost:4000/upload</cite> with a formdata with a file. Select the &quot;send and Download&quot; instead of &quot;Send&quot; and you should have an image after that. Bellow an image of how your postman should be.</p> +<img alt="Postman" src="/images/microservice_postman.png" /> +<p>That's it for today, next week we'll change our code to use RabbitMQ.</p> +Connecting to a database through SSH2018-03-29T10:03:00-03:002018-03-29T10:03:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-03-29:/en/connecting_to_database_through_ssh.html<p>If someday, for some reason, you need to establish a connection with a database which is behind a firewall and you only have SSH access on that server (and you don't want to use a CLI) you can do an SSH tunnel. It's pretty simple, bellow has a sample of …</p><p>If someday, for some reason, you need to establish a connection with a database which is behind a firewall and you only have SSH access on that server (and you don't want to use a CLI) you can do an SSH tunnel. It's pretty simple, bellow has a sample of how to allow connections to a remote Firebird database.</p> +<div class="highlight"><pre><span></span>ssh -L <span class="m">3051</span>:192.168.1.9:3050 username@192.168.1.9 +</pre></div> +<p>The <cite>-L</cite> parameter tells to SSH do a local port forwarding on local port <cite>3051</cite> to remote port <cite>3050</cite>. You can use it to a connection with many services, not just databases.</p> +<p>You can do the reverse kind of tunnel, forward connections from the host to your local machine, you just have to change the parameter form &quot;-L&quot; to &quot;-R&quot; and the port order is inverted, first come the port where the server will listen and after your localhost port. This remote port forwarding must be enabled on the server. Look for <cite>GatewayPorts</cite> at the ssh config file.</p> +<div class="highlight"><pre><span></span>ssh -R <span class="m">3050</span>:localhost:3050 username@192.168.1.9 +</pre></div> +<p>Why whould you need something like that?? Let's say you want to share a localhost site/database with a friend, but your internet connection don't allow you to expose any port but you have access to a remote server witch can do that. Problem solved ;).</p> +Now posting on Grepora2018-03-24T00:40:00-03:002018-03-24T00:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-03-24:/en/now_posting_on_grepora.html<p>A few weeks ago I started posting at <a class="reference external" href="https://grepora.com/blog/">Grepora</a> blog. If you like or are looking for some Oracle related stuff, Grepora it's a good place to go and spend a time reading :). From time to time I'll be posting there, it doesn't mean that this blog will be closed …</p><p>A few weeks ago I started posting at <a class="reference external" href="https://grepora.com/blog/">Grepora</a> blog. If you like or are looking for some Oracle related stuff, Grepora it's a good place to go and spend a time reading :). From time to time I'll be posting there, it doesn't mean that this blog will be closed or anything like that, but probably this one will be more focused on Front-end stuff, a few tricks with linux and a lil less with Java.</p> +Scaffolding a React app with Parcel and Yeoman2018-03-17T13:00:00-03:002018-03-17T13:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-03-17:/en/scaffolding_react_app_with_parcel_yeoman.html<p>Since <a class="reference external" href="https://parceljs.org/">Parcel JS</a> arrived, I've been using it a lot as an awesome alternative for WebPack. Webpack isn't bad but IMO it's too complex for the job and parcel do the same (at least the basic) with almost zero configuration. But if you need to create many apps (like a …</p><p>Since <a class="reference external" href="https://parceljs.org/">Parcel JS</a> arrived, I've been using it a lot as an awesome alternative for WebPack. Webpack isn't bad but IMO it's too complex for the job and parcel do the same (at least the basic) with almost zero configuration. But if you need to create many apps (like a react app) over and over again, it get's a lil boring following the basic steps.</p> +<div class="highlight"><pre><span></span>npm init -y +npm install --save react +npm install --save react-dom +npm install --save-dev parcel-bundler +npm install --save-dev babel-preset-env +npm install --save-dev babel-preset-react + +<span class="c1">#create .babelrc file</span> +<span class="c1">#create html, css, jsx files</span> + +parcel index.html +</pre></div> +<p>It's not a hard job, a simple shell script do the job, but what if you need some IFs when creating the app, or even change a few things at the <cite>package.json</cite>? A shell script still does the job, but come on... There is a better way. <a class="reference external" href="http://yeoman.io/">Yeoman</a> is here for you. I've already <a class="reference external" href="https://www.sipmann.com/en/desenvolvendo-app-firefoxos-pt.html">talked about it</a> on another post (Portuguese post).</p> +<p>Straight to the point, I've released a Yeoman generator to get the things a lil quicker. The name is <a class="reference external" href="https://www.npmjs.com/package/generator-parcel-react">generator-parcel-react</a> and it still lacks a few things that I will deal with soon. It's pretty simple to use it.</p> +<div class="highlight"><pre><span></span><span class="c1">#First time only</span> +npm install -g yo +npm install -g generator-parcel-react + +<span class="c1">#every time you create a new app</span> +yo parcel-react +</pre></div> +<p>And that's it. Right now you can scaffold and app with React, SASS and React Router. Hope you like it and feel free to ask new features.</p> +Could not open connection with MySQL and Hibernate2018-03-09T12:35:00-03:002018-03-09T12:35:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-03-09:/en/cloud-not-open-connection-java-mysql-hibernate.html<p>Last day I decided to deploy a MySQL Docker image to work with my Java application. I've been using PostgreSQL instead and have no problems at all, but after I moved to MySQL, the app didn't connect anymore with the database and throw some &quot;Could not open connection&quot; at my …</p><p>Last day I decided to deploy a MySQL Docker image to work with my Java application. I've been using PostgreSQL instead and have no problems at all, but after I moved to MySQL, the app didn't connect anymore with the database and throw some &quot;Could not open connection&quot; at my face, but why? I've tried to connect to it manually and got the same problem.</p> +<p>After some research, I found that the true error should be java.sql.SQLException: null, message from server: &quot;Host '172.17.0.4' is not allowed to connect to this MySQL server&quot; but it wasn't showing to me...</p> +<p>After all, be aware that with the docker image MySQL:5.7.21 (latest version right now) the root user isn't allowed to remote connect to the database (it's alright, security reasons) and if you still want to do remote connections to it with root there are a few things you can do.</p> +<ol class="arabic simple"> +<li>Create a user or allow root to access from other IPs.</li> +</ol> +<div class="highlight"><pre><span></span><span class="o">#</span><span class="k">No</span> <span class="k">access</span> <span class="k">to</span> <span class="k">user</span> <span class="n">root</span> <span class="k">on</span> <span class="k">any</span> <span class="n">other</span> <span class="n">IP</span> +<span class="k">SELECT</span> <span class="k">User</span><span class="p">,</span> <span class="k">Host</span> <span class="k">FROM</span> <span class="n">mysql</span><span class="p">.</span><span class="k">user</span><span class="p">;</span> +<span class="o">+</span><span class="c1">---------------+-----------+</span> +<span class="o">|</span> <span class="k">User</span> <span class="o">|</span> <span class="k">Host</span> <span class="o">|</span> +<span class="o">+</span><span class="c1">---------------+-----------+</span> +<span class="o">|</span> <span class="n">healthchecker</span> <span class="o">|</span> <span class="n">localhost</span> <span class="o">|</span> +<span class="o">|</span> <span class="n">root</span> <span class="o">|</span> <span class="n">localhost</span> <span class="o">|</span> +<span class="o">+</span><span class="c1">---------------+-----------+</span> +<span class="mi">2</span> <span class="k">rows</span> <span class="k">in</span> <span class="k">set</span> <span class="p">(</span><span class="mi">0</span><span class="p">.</span><span class="mi">01</span> <span class="n">sec</span><span class="p">)</span> + +<span class="k">CREATE</span> <span class="k">USER</span> <span class="s1">&#39;newuser&#39;</span><span class="o">@</span><span class="s1">&#39;%&#39;</span> <span class="n">IDENTIFIED</span> <span class="k">BY</span> <span class="s1">&#39;password&#39;</span><span class="p">;</span> <span class="o">#%</span> <span class="n">mean</span> <span class="k">any</span> <span class="n">IP</span> +<span class="k">GRANT</span> <span class="k">ALL</span> <span class="k">PRIVILEGES</span> <span class="k">ON</span> <span class="o">*</span><span class="p">.</span><span class="o">*</span> <span class="k">TO</span> <span class="s1">&#39;newuser&#39;</span><span class="o">@</span><span class="s1">&#39;%&#39;</span><span class="p">;</span> <span class="o">#*</span><span class="p">.</span><span class="o">*</span> <span class="n">mean</span> <span class="k">database</span><span class="p">.</span><span class="k">table</span> <span class="p">;)</span> +</pre></div> +<ol class="arabic simple" start="2"> +<li>Use MariaDB instead, witch come (at least on the version 10.2.13) with root allowed to do remote connections and will work like MySQL :)</li> +</ol> +<p>I changed to <a class="reference external" href="https://mariadb.org/">MariaDB</a> as it work without creating user or any changes on the Java code or the <cite>docker run command</cite>.</p> +Solving java.net.SocketException: Protocol family unavailable on a Java + Docker + WildFly2018-03-04T17:40:00-03:002018-03-04T17:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-03-04:/en/socketException-protocol-family-unavailable-java-docker-wildfly.html<p>On the last days I've been playing with <a class="reference external" href="http://wildfly-swarm.io/">WildFly Swarm</a> and I decided to deploy a simple app with Docker. Should work fine, at least that was what I thought. Built a container with the following Dockerfile and instead of a working web app, all that I got was the …</p><p>On the last days I've been playing with <a class="reference external" href="http://wildfly-swarm.io/">WildFly Swarm</a> and I decided to deploy a simple app with Docker. Should work fine, at least that was what I thought. Built a container with the following Dockerfile and instead of a working web app, all that I got was the error <cite>java.net.SocketException: Protocol family unavailable</cite>.</p> +<div class="highlight"><pre><span></span><span class="k">FROM</span> <span class="s">java:openjdk-8-jdk</span> + +<span class="k">COPY</span> target/issues.jar /opt/issues.jar + +<span class="k">EXPOSE</span><span class="s"> 8080</span> + +<span class="k">CMD</span> <span class="p">[</span><span class="s2">&quot;java&quot;</span><span class="p">,</span><span class="s2">&quot;-jar&quot;</span><span class="p">,</span><span class="s2">&quot;/opt/issues.jar&quot;</span><span class="p">]</span> +</pre></div> +<p>For some reason, WildFly and Java decided to use the IPv6 network interface from Docker instead the v4, so all you have to do is tell Java to prefer IPv4 instead with the following configuration option in your pom.xml file inside your WildFly plugin.</p> +<div class="highlight"><pre><span></span><span class="nt">&lt;plugin&gt;</span> + <span class="nt">&lt;groupId&gt;</span>org.wildfly.swarm<span class="nt">&lt;/groupId&gt;</span> + <span class="nt">&lt;artifactId&gt;</span>wildfly-swarm-plugin<span class="nt">&lt;/artifactId&gt;</span> + <span class="nt">&lt;version&gt;</span>2018.2.0<span class="nt">&lt;/version&gt;</span> + + <span class="c">&lt;!-- ADD THIS --&gt;</span> + <span class="nt">&lt;configuration&gt;</span> + <span class="nt">&lt;mainClass&gt;</span>org.wildfly.swarm.examples.netflix.ribbon.frontend.Main<span class="nt">&lt;/mainClass&gt;</span> + <span class="nt">&lt;properties&gt;</span> + <span class="nt">&lt;java.net.preferIPv4Stack&gt;</span>true<span class="nt">&lt;/java.net.preferIPv4Stack&gt;</span> + <span class="nt">&lt;/properties&gt;</span> + <span class="nt">&lt;/configuration&gt;</span> +</pre></div> +<p>Another way to solve is adding the same properties to the run command at the Dockerfile, so you choose where you'll add it. Bellow the Dockerfile solution.</p> +<div class="highlight"><pre><span></span><span class="k">FROM</span> <span class="s">java:openjdk-8-jdk</span> +<span class="k">ENV</span> <span class="nv">JAVA_OPTS</span><span class="o">=</span><span class="s2">&quot;-Djava.net.preferIPv4Stack=true -Djava.net.preferIPv4Addresses=true&quot;</span> + +<span class="k">COPY</span> target/issues.jar /opt/issues.jar + +<span class="k">EXPOSE</span><span class="s"> 8080</span> + +<span class="k">ENTRYPOINT</span> <span class="nb">exec</span> java <span class="nv">$JAVA_OPTS</span> -jar /opt/issues.jar +</pre></div> +Resolvendo java.net.SocketException: Protocol family unavailable em Java + Docker + WildFly2018-03-04T17:40:00-03:002018-03-04T17:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-03-04:/pt/socketException-protocol-family-unavailable-java-docker-wildfly.html<p>Nos últimos dias eu estou brincando com o <a class="reference external" href="http://wildfly-swarm.io/">WildFly Swarm</a> e decidi fazer o deploy de uma aplicação simples com Docker. Deveria funcionar bem, ao menos é o que pensava. Construí um container com o seguinte Dockerfile e ao invés de obter uma aplicação web, tudo que eu obtive foi …</p><p>Nos últimos dias eu estou brincando com o <a class="reference external" href="http://wildfly-swarm.io/">WildFly Swarm</a> e decidi fazer o deploy de uma aplicação simples com Docker. Deveria funcionar bem, ao menos é o que pensava. Construí um container com o seguinte Dockerfile e ao invés de obter uma aplicação web, tudo que eu obtive foi o erro <cite>java.net.SocketException: Protocol family unavailable</cite>.</p> +<div class="highlight"><pre><span></span><span class="k">FROM</span> <span class="s">java:openjdk-8-jdk</span> + +<span class="k">COPY</span> target/issues.jar /opt/issues.jar + +<span class="k">EXPOSE</span><span class="s"> 8080</span> + +<span class="k">CMD</span> <span class="p">[</span><span class="s2">&quot;java&quot;</span><span class="p">,</span><span class="s2">&quot;-jar&quot;</span><span class="p">,</span><span class="s2">&quot;/opt/issues.jar&quot;</span><span class="p">]</span> +</pre></div> +<p>Por alguma razão, WildFly e Java, ambos decidiram utilizar um protocolo IPv6 na interface de rede no Docker invés da v4, então tudo que você tem que fazer é falar ao Java que deve dar preferência em utilizar o IPv4 com a seguinte configuração no seu arquivo pom.xml dentro da tag do plugin WildFly.</p> +<div class="highlight"><pre><span></span><span class="nt">&lt;plugin&gt;</span> + <span class="nt">&lt;groupId&gt;</span>org.wildfly.swarm<span class="nt">&lt;/groupId&gt;</span> + <span class="nt">&lt;artifactId&gt;</span>wildfly-swarm-plugin<span class="nt">&lt;/artifactId&gt;</span> + <span class="nt">&lt;version&gt;</span>2018.2.0<span class="nt">&lt;/version&gt;</span> + + <span class="c">&lt;!-- ADICIONE ISTO --&gt;</span> + <span class="nt">&lt;configuration&gt;</span> + <span class="nt">&lt;mainClass&gt;</span>org.wildfly.swarm.examples.netflix.ribbon.frontend.Main<span class="nt">&lt;/mainClass&gt;</span> + <span class="nt">&lt;properties&gt;</span> + <span class="nt">&lt;java.net.preferIPv4Stack&gt;</span>true<span class="nt">&lt;/java.net.preferIPv4Stack&gt;</span> + <span class="nt">&lt;/properties&gt;</span> + <span class="nt">&lt;/configuration&gt;</span> +</pre></div> +<p>Outra forma de solucionar o problema, é adicionando a mesma propriedade ao comando de run no seu Dockerfile. Então, fica a seu critério onde adicionar. Abaixo a solução utilizando o Dockerfile.</p> +<div class="highlight"><pre><span></span><span class="k">FROM</span> <span class="s">java:openjdk-8-jdk</span> +<span class="k">ENV</span> <span class="nv">JAVA_OPTS</span><span class="o">=</span><span class="s2">&quot;-Djava.net.preferIPv4Stack=true -Djava.net.preferIPv4Addresses=true&quot;</span> + +<span class="k">COPY</span> target/issues.jar /opt/issues.jar + +<span class="k">EXPOSE</span><span class="s"> 8080</span> + +<span class="k">ENTRYPOINT</span> <span class="nb">exec</span> java <span class="nv">$JAVA_OPTS</span> -jar /opt/issues.jar +</pre></div> +Change display settings on linux with Disper2018-02-27T12:40:00-03:002018-02-27T12:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-02-27:/en/linux-external-display-with-disper.html<p>From time to time, I change the Linux distro on my laptop or just do a fresh install on it. And once in a while, have random problems with external displays. It can be something really &quot;simple&quot; like don't detecting the external monitor or something crazy like the image below …</p><p>From time to time, I change the Linux distro on my laptop or just do a fresh install on it. And once in a while, have random problems with external displays. It can be something really &quot;simple&quot; like don't detecting the external monitor or something crazy like the image below.</p> +<img alt="Display bug" src="/images/bug.png" /> +<p>As you can see at the image, the mint detected the display but mirrored it in a crazy way that works but doesn't at the same time. If you try anything and doesn't get working, or just wanna skip the whole job of configuring complexes text files, give a try to <a class="reference external" href="http://willem.engen.nl/projects/disper/">Disper</a>. Download the latest version. +Extract it on any folder, and make install it (on the extracted folder).</p> +<div class="highlight"><pre><span></span>make install +</pre></div> +<p>After that, you can start using it... There are a few options that will serve you well.</p> +<div class="highlight"><pre><span></span>disper -e <span class="c1">#extend your display</span> +</pre></div> +<div class="highlight"><pre><span></span>disper -c <span class="c1">#clone your display</span> +</pre></div> +<div class="highlight"><pre><span></span>disper -s <span class="c1">#only your external display</span> +</pre></div> +Java - Files.readAllBytes throws OutOfMemory2018-02-17T13:00:00-02:002018-02-17T13:00:00-02:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-02-17:/en/reading-files-java-readAllBytes-outofmemory.html<p>When you need to interact with files, there's the possibility to read all bytes from the file with <cite>Files.readAllBytes</cite>. But be aware of the kinds of files your application will deal with because the Java API files have a limit for the buffer that is defined as <cite>Integer.MAX_VALUE …</cite></p><p>When you need to interact with files, there's the possibility to read all bytes from the file with <cite>Files.readAllBytes</cite>. But be aware of the kinds of files your application will deal with because the Java API files have a limit for the buffer that is defined as <cite>Integer.MAX_VALUE</cite> as you can see above or at the OpenJDK sources.</p> +<div class="highlight"><pre><span></span><span class="kd">public</span> <span class="kd">static</span> <span class="kt">byte</span><span class="o">[]</span> <span class="nf">readAllBytes</span><span class="p">(</span><span class="n">Path</span> <span class="n">path</span><span class="p">)</span> <span class="kd">throws</span> <span class="n">IOException</span> <span class="p">{</span> + <span class="k">try</span> <span class="p">(</span><span class="n">FileChannel</span> <span class="n">fc</span> <span class="o">=</span> <span class="n">FileChannel</span><span class="p">.</span><span class="na">open</span><span class="p">(</span><span class="n">path</span><span class="p">))</span> <span class="p">{</span> + <span class="kt">long</span> <span class="n">size</span> <span class="o">=</span> <span class="n">fc</span><span class="p">.</span><span class="na">size</span><span class="p">();</span> + <span class="k">if</span> <span class="p">(</span><span class="n">size</span> <span class="o">&gt;</span> <span class="p">(</span><span class="kt">long</span><span class="p">)</span><span class="n">Integer</span><span class="p">.</span><span class="na">MAX_VALUE</span><span class="p">)</span> + <span class="k">throw</span> <span class="k">new</span> <span class="n">OutOfMemoryError</span><span class="p">(</span><span class="s">&quot;Required array size too large&quot;</span><span class="p">);</span> + + <span class="kt">byte</span><span class="o">[]</span> <span class="n">arr</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">byte</span><span class="o">[</span><span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">size</span><span class="o">]</span><span class="p">;</span> + <span class="n">ByteBuffer</span> <span class="n">bb</span> <span class="o">=</span> <span class="n">ByteBuffer</span><span class="p">.</span><span class="na">wrap</span><span class="p">(</span><span class="n">arr</span><span class="p">);</span> + <span class="k">while</span> <span class="p">(</span><span class="n">bb</span><span class="p">.</span><span class="na">hasRemaining</span><span class="p">())</span> <span class="p">{</span> + <span class="k">if</span> <span class="p">(</span><span class="n">fc</span><span class="p">.</span><span class="na">read</span><span class="p">(</span><span class="n">bb</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> + <span class="c1">// truncated</span> + <span class="k">break</span><span class="p">;</span> + <span class="p">}</span> + <span class="p">}</span> + + <span class="kt">int</span> <span class="n">nread</span> <span class="o">=</span> <span class="n">bb</span><span class="p">.</span><span class="na">position</span><span class="p">();</span> + <span class="k">return</span> <span class="p">(</span><span class="n">nread</span> <span class="o">==</span> <span class="n">size</span><span class="p">)</span> <span class="o">?</span> <span class="n">arr</span> <span class="p">:</span> <span class="n">Arrays</span><span class="p">.</span><span class="na">copyOf</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="n">nread</span><span class="p">);</span> + <span class="p">}</span> +<span class="p">}</span> +</pre></div> +<p>With that in mind, check if isn't better read chunks of bytes e work with that slice in exchange of loading the whole file into the memory ;). Above a simple example of how you can read chunks of bytes from the file.</p> +<div class="highlight"><pre><span></span><span class="kt">byte</span><span class="o">[]</span> <span class="n">buffer</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">byte</span><span class="o">[</span><span class="mi">1024</span><span class="o">]</span><span class="p">;</span> +<span class="n">FileInputStream</span> <span class="n">in</span> <span class="o">=</span> <span class="k">new</span> <span class="n">FileInputStream</span><span class="p">(</span><span class="n">file</span><span class="p">);</span> +<span class="kt">int</span> <span class="n">rc</span> <span class="o">=</span> <span class="n">in</span><span class="p">.</span><span class="na">read</span><span class="p">(</span><span class="n">buffer</span><span class="p">);</span> +<span class="k">while</span> <span class="p">(</span><span class="n">rc</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span> +<span class="p">{</span> + <span class="c1">//crazy stuff here with buffer</span> + <span class="n">rc</span> <span class="o">=</span> <span class="n">in</span><span class="p">.</span><span class="na">read</span><span class="p">(</span><span class="n">buffer</span><span class="p">);</span> +<span class="p">}</span> +</pre></div> + \ No newline at end of file diff --git a/en/feeds/all.atom.xml.gz b/en/feeds/all.atom.xml.gz new file mode 100644 index 000000000..bc665af0b Binary files /dev/null and b/en/feeds/all.atom.xml.gz differ diff --git a/en/feeds/azure.atom.xml b/en/feeds/azure.atom.xml new file mode 100644 index 000000000..0c93cfad2 --- /dev/null +++ b/en/feeds/azure.atom.xml @@ -0,0 +1,52 @@ + +Sipmann - Azurehttps://www.sipmann.com/en/2020-10-03T19:00:00-03:00Microsoft Against Covid2020-10-03T19:00:00-03:002020-10-03T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-03:/en/microsoft-against-covid.html<p>Has your job been affected by covid? Well, last week I've posted on <a href="https://grepora.com/2020/09/17/microsoft-ignite-certification-voucher/">Grepora</a> about a Free Certification Voucher that Microsoft was giving away at the Microsoft Ignite event. After that, I found that they were also giving a huge discount to people who have had their job affected by …</p><p>Has your job been affected by covid? Well, last week I've posted on <a href="https://grepora.com/2020/09/17/microsoft-ignite-certification-voucher/">Grepora</a> about a Free Certification Voucher that Microsoft was giving away at the Microsoft Ignite event. After that, I found that they were also giving a huge discount to people who have had their job affected by covid pandemic. </p> +<p>To see more details about if you were eligible, access <a href="https://docs.microsoft.com/en-us/learn/certifications/skillingoffer">https://docs.microsoft.com/en-us/learn/certifications/skillingoffer</a>.</p>Monitoring a Website heath with Azure Functions2020-06-22T19:00:00-03:002020-06-22T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-06-22:/en/monitoring-website-heath-with-azure-functions.html<p>Sometimes you get your self in need to monitor a website's health or it's content for changes. Of course, there's plenty of options out there, but for the sake of curiosity, let's code our own to see what we can do. First things first. Everything you'll see here, you can …</p><p>Sometimes you get your self in need to monitor a website's health or it's content for changes. Of course, there's plenty of options out there, but for the sake of curiosity, let's code our own to see what we can do. First things first. Everything you'll see here, you can achieve with the <a href="https://azure.microsoft.com/free/">free tier</a> of azure.</p> +<p>The main idea of our app will be to monitor website health (status code). To create a new Azure Function Project, follow the steps below.</p> +<p><img alt="Steps to create a azure function project" src="/images/azure_functions.gif"></p> +<p>After creating the project, you'll have a few files. Open your main file and start coding. The main file will have a function called <code>Run</code> and you can code your request method. I've created an <code>async</code> method to make the request and log the output at the console. The full code you can see below.</p> +<div class="highlight"><pre><span></span><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Linq</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Net.Http</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Threading.Tasks</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">Microsoft.Azure.WebJobs</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">Microsoft.Azure.WebJobs.Host</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">Microsoft.Extensions.Logging</span><span class="p">;</span> + +<span class="k">namespace</span> <span class="nn">Sipmann.CheckMySite</span> +<span class="p">{</span> + <span class="k">public</span> <span class="k">static</span> <span class="k">class</span> <span class="nc">HttpCheck</span> + <span class="p">{</span> + + <span class="k">private</span> <span class="k">static</span> <span class="k">async</span> <span class="n">Task</span> <span class="nf">GetTask</span><span class="p">(</span><span class="kt">string</span> <span class="n">url</span><span class="p">,</span> <span class="n">ILogger</span> <span class="n">log</span><span class="p">)</span> + <span class="p">{</span> + <span class="kt">var</span> <span class="n">request</span> <span class="p">=</span> <span class="k">new</span> <span class="n">HttpRequestMessage</span><span class="p">(</span><span class="n">HttpMethod</span><span class="p">.</span><span class="n">Get</span><span class="p">,</span> <span class="n">url</span><span class="p">);</span> + + <span class="kt">var</span> <span class="n">client</span> <span class="p">=</span> <span class="k">new</span> <span class="n">HttpClient</span><span class="p">();</span> + <span class="kt">var</span> <span class="n">response</span> <span class="p">=</span> <span class="k">await</span> <span class="n">client</span><span class="p">.</span><span class="n">SendAsync</span><span class="p">(</span><span class="n">request</span><span class="p">);</span> + + <span class="k">if</span> <span class="p">(</span><span class="n">response</span><span class="p">.</span><span class="n">IsSuccessStatusCode</span><span class="p">)</span> + <span class="p">{</span> + <span class="n">log</span><span class="p">.</span><span class="n">LogInformation</span><span class="p">(</span><span class="err">$</span><span class="s">&quot;URL ${url} esta OK&quot;</span><span class="p">);</span> + <span class="p">}</span> + <span class="k">else</span> + <span class="p">{</span> + <span class="n">log</span><span class="p">.</span><span class="n">LogInformation</span><span class="p">(</span><span class="err">$</span><span class="s">&quot;URL ${url} não esta OK&quot;</span><span class="p">);</span> + <span class="p">}</span> + <span class="p">}</span> + +<span class="na"> [FunctionName(&quot;HttpCheck&quot;)]</span> + <span class="k">public</span> <span class="k">static</span> <span class="k">void</span> <span class="nf">Run</span><span class="p">([</span><span class="n">TimerTrigger</span><span class="p">(</span><span class="s">&quot;0 */5 * * * *&quot;</span><span class="p">)]</span><span class="n">TimerInfo</span> <span class="n">myTimer</span><span class="p">,</span> <span class="n">ILogger</span> <span class="n">log</span><span class="p">)</span> + <span class="p">{</span> + <span class="kt">var</span> <span class="n">urls</span> <span class="p">=</span> <span class="k">new</span><span class="p">[]{</span><span class="s">&quot;https://www.sipmann.com&quot;</span><span class="p">,</span> <span class="s">&quot;https://www.canezecanez.com.br&quot;</span><span class="p">};</span> + + <span class="c1">// Start every request and wait for them all to complete</span> + <span class="n">Task</span><span class="p">.</span><span class="n">WaitAll</span><span class="p">(</span><span class="n">urls</span><span class="p">.</span><span class="n">Select</span><span class="p">(</span><span class="n">url</span> <span class="p">=&gt;</span> <span class="n">GetTask</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">log</span><span class="p">)).</span><span class="n">ToArray</span><span class="p">());</span> + <span class="n">log</span><span class="p">.</span><span class="n">LogInformation</span><span class="p">(</span><span class="err">$</span><span class="s">&quot;Finalizou a fila&quot;</span><span class="p">);</span> + <span class="p">}</span> + <span class="p">}</span> +<span class="p">}</span> +</code></pre></div> + +<p>Now you can enhance the function and maybe send some alerts like a Telegram message when one of your sites went down.</p>Azure Data Fundamentals certification with 80% discount2020-06-09T12:30:00-03:002020-06-09T12:30:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-06-09:/en/azure-data-fundamentals-certification-80-discount.html<p>Hey folks, if you want to achieve some certification this year, keep an eye open for vouchers. A few months ago, Oracle released a set of free courses with certifications. Now it's Microsoft time. Microsoft is updating they're certifications and we have a voucher of 80% discount using the coupon …</p><p>Hey folks, if you want to achieve some certification this year, keep an eye open for vouchers. A few months ago, Oracle released a set of free courses with certifications. Now it's Microsoft time. Microsoft is updating they're certifications and we have a voucher of 80% discount using the coupon <strong>DP900Norfolk</strong> at the checkout of the beta certification DP-900. </p> +<p>Be aware that this certification is in beta and the result won't be instantly available as the regular ones. Access the following link and schedule your exam. <a href="https://docs.microsoft.com/pt-br/learn/certifications/exams/dp-900" target="_blank">https://docs.microsoft.com/pt-br/learn/certifications/exams/dp-900</a>.</p> +<p><strong>Update:</strong> There is a 80% voucher also for <a href="https://docs.microsoft.com/en-us/learn/certifications/azure-ai-fundamentals" target="_blank">https://docs.microsoft.com/en-us/learn/certifications/azure-ai-fundamentals</a>. Voucher: <strong>AI900Saratoga</strong></p> \ No newline at end of file diff --git a/en/feeds/azure.atom.xml.gz b/en/feeds/azure.atom.xml.gz new file mode 100644 index 000000000..61948b941 Binary files /dev/null and b/en/feeds/azure.atom.xml.gz differ diff --git a/en/feeds/flutter.atom.xml b/en/feeds/flutter.atom.xml new file mode 100644 index 000000000..ea98d9b81 --- /dev/null +++ b/en/feeds/flutter.atom.xml @@ -0,0 +1,28 @@ + +Sipmann - Flutterhttps://www.sipmann.com/en/2019-10-03T19:00:00-03:00Flutter + firebase auth crashing2019-10-03T19:00:00-03:002019-10-03T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2019-10-03:/en/flutter_with_firebase_auth_crashing.html<p>Hey Folks, recently I've started learning <a href="https://flutter.dev/">Flutter</a> and right after a TODO List, I tried a Firebase integration. But as soon as I started setting the dependencies, my app stopped opening... just a crash. After a few logs digging, I've found the following log.</p> +<div class="highlight"><pre><span></span><code>AndroidRuntime: FATAL EXCEPTION: main +AndroidRuntime: Process …</code></pre></div><p>Hey Folks, recently I've started learning <a href="https://flutter.dev/">Flutter</a> and right after a TODO List, I tried a Firebase integration. But as soon as I started setting the dependencies, my app stopped opening... just a crash. After a few logs digging, I've found the following log.</p> +<div class="highlight"><pre><span></span><code>AndroidRuntime: FATAL EXCEPTION: main +AndroidRuntime: Process: com.example.diadocasal, PID: <span class="m">13672</span> +AndroidRuntime: java.lang.NoClassDefFoundError: Failed resolution of: Landroid/support/v4/util/ArrayMap<span class="p">;</span> +AndroidRuntime: at com.google.android.gms.internal.measurement.zzca.&lt;clinit&gt;<span class="o">(</span>Unknown Source:60<span class="o">)</span> +AndroidRuntime: at com.google.android.gms.internal.measurement.zzcm.zzr<span class="o">(</span>Unknown Source:7<span class="o">)</span> +AndroidRuntime: at com.google.android.gms.measurement.internal.zzfj.&lt;init&gt;<span class="o">(</span>Unknown Source:23<span class="o">)</span> +</code></pre></div> + +<p>Notice the "NoClassDefFound" of an ArrayMap. To solve that I did the following changes to the files:</p> +<div class="highlight"><pre><span></span><code><span class="c1">//build.gradle file</span> + <span class="n">ext</span><span class="p">.</span><span class="na">kotlin_version</span> <span class="o">=</span> <span class="err">&#39;</span><span class="mf">1.3.20</span><span class="err">&#39;</span> +<span class="o">[</span><span class="p">...</span><span class="o">]</span> + <span class="n">dependencies</span> <span class="p">{</span> + <span class="n">classpath</span> <span class="err">&#39;</span><span class="n">com</span><span class="p">.</span><span class="na">android</span><span class="p">.</span><span class="na">tools</span><span class="p">.</span><span class="na">build</span><span class="p">:</span><span class="n">gradle</span><span class="p">:</span><span class="mf">3.3.0</span><span class="err">&#39;</span> <span class="c1">// gradle version</span> +</code></pre></div> + +<div class="highlight"><pre><span></span><code><span class="c1">;gradle.properties file</span> +<span class="na">org.gradle.jvmargs</span><span class="o">=</span><span class="s">-Xmx1536M ;mine have just this line at first</span> +<span class="na">android.useAndroidX</span><span class="o">=</span><span class="s">true ; uses androidX instead of the default support library</span> +<span class="na">android.enableJetifier</span><span class="o">=</span><span class="s">true ; uses jetpack libraries</span> +<span class="na">android.enableR8</span><span class="o">=</span><span class="s">true ; the new code shriker</span> +</code></pre></div> + +<p>After that, voilà, app up and running.</p> \ No newline at end of file diff --git a/en/feeds/flutter.atom.xml.gz b/en/feeds/flutter.atom.xml.gz new file mode 100644 index 000000000..d41ea2ab2 Binary files /dev/null and b/en/feeds/flutter.atom.xml.gz differ diff --git a/en/feeds/front-end.atom.xml b/en/feeds/front-end.atom.xml new file mode 100644 index 000000000..0513a56e2 --- /dev/null +++ b/en/feeds/front-end.atom.xml @@ -0,0 +1,178 @@ + +Sipmann - Front-endhttps://www.sipmann.com/en/2018-04-13T13:00:00-03:00Microservices with NodeJS, Express.js and RabbitMQ Part 22018-04-13T13:00:00-03:002018-04-13T13:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-04-13:/en/microservices_nodejs_express_rabbitmq_part_2.html<p>If you haven't read the <a class="reference external" href="https://www.sipmann.com/microservices_nodejs_express_rabbitmq_part_1-en.html">part 1</a> go ahead and read it... It can be useful :). Or if for some reason you want to start now, you can grab the project where we stopped <a class="reference external" href="https://github.com/sipmann/imagecompacter/releases/tag/v1">here</a> and get along. On this part, we'll implement the RabbitMQ queue and see how we …</p><p>If you haven't read the <a class="reference external" href="https://www.sipmann.com/microservices_nodejs_express_rabbitmq_part_1-en.html">part 1</a> go ahead and read it... It can be useful :). Or if for some reason you want to start now, you can grab the project where we stopped <a class="reference external" href="https://github.com/sipmann/imagecompacter/releases/tag/v1">here</a> and get along. On this part, we'll implement the RabbitMQ queue and see how we can get the best of our app and server with that.</p> +<p>Before we began coding, let's understand why we are going to use RabbitMQ if what we have now works? If you check again, you'll see how long it takes to answer the request with the optimized image. It takes a few seconds, so imagine an online service with thousands of request to optimize images (like <a class="reference external" href="https://tinypng.com/">TinyPNG</a>) how long is it gonna take to answer every request? How much of your server is it gonna take? With only one service running, probably the server will crash.</p> +<p>With a queue, we can schedule the requests so we can use the amount of memory and processor that our server has, without taking more than we can. It's better to take a few seconds to answer the request then throw some error to the user. Want more? With RabbitMQ we can see how the queue is doing and we can add more consumers (workers) to it and get things done quicker and distribute the job.</p> +<p>First of all, we need an up and running Rabbit server, for the sake of simplicity, I'll use a Docker container with it inside.</p> +<div class="highlight"><pre><span></span>docker run -d --name rabbit -p <span class="m">5672</span>:5672 -p <span class="m">8080</span>:15672 rabbitmq:3-management +</pre></div> +<p>You can see that we're running the rabbitmq:3-management image, which provides us a web interface to see how things are going. After that, if you look at our code you'll see that all the job is made at the '/upload' route, and that's what we'll change.</p> +<p>First, we need to understand what we need from RabbitMQ. We need something that, we send an image to a queue and get an optimized image back from that. There is a name for that, is RPC (remote procedure call) and there are two ways of doing this with rabbit. Both the ways you can see on their tutorial page. We'll use the approach that uses a global channel whose id is randomly generated (you'll use the name 'amq.rabbitmq.reply-to' but the rabbit will do the job).</p> +<p>Let's start importing the library, defining a few variables and defining a init function that will establish a connection with the rabbit server and create our RPC queue. The RPC queue it's where we'll receive the answer from the consumer (our worker).</p> +<div class="highlight"><pre><span></span><span class="c1">//import the library</span> +<span class="kr">const</span> <span class="nx">amqplib</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;amqplib&#39;</span><span class="p">);</span> + +<span class="c1">//queue channel</span> +<span class="kd">let</span> <span class="nx">channel</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span> +<span class="c1">//queue name</span> +<span class="kr">const</span> <span class="nx">QUEUE</span> <span class="o">=</span> <span class="s1">&#39;optimizeimg&#39;</span><span class="p">;</span> + +<span class="c1">//...</span> + +<span class="kd">function</span> <span class="nx">init</span><span class="p">()</span> <span class="p">{</span> + <span class="k">return</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;amqplib&#39;</span><span class="p">).</span><span class="nx">connect</span><span class="p">(</span><span class="s1">&#39;amqp://localhost&#39;</span><span class="p">)</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">conn</span> <span class="p">=&gt;</span> <span class="nx">conn</span><span class="p">.</span><span class="nx">createChannel</span><span class="p">())</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">ch</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="nx">channel</span> <span class="o">=</span> <span class="nx">ch</span><span class="p">;</span> + + <span class="c1">//this queue is a &quot;Direct reply-to&quot; read more at the docs</span> + <span class="c1">//When some msg comes in, we &quot;emit&quot; a message to the proper &quot;correlationId&quot; listener</span> + <span class="nx">ch</span><span class="p">.</span><span class="nx">consume</span><span class="p">(</span><span class="s1">&#39;amq.rabbitmq.reply-to&#39;</span><span class="p">,</span> <span class="nx">msg</span> <span class="p">=&gt;</span> <span class="nx">eventEmitter</span><span class="p">.</span><span class="nx">emit</span><span class="p">(</span><span class="nx">msg</span><span class="p">.</span><span class="nx">properties</span><span class="p">.</span><span class="nx">correlationId</span><span class="p">,</span> <span class="nx">msg</span><span class="p">.</span><span class="nx">content</span><span class="p">),</span> <span class="p">{</span><span class="nx">noAck</span><span class="o">:</span> <span class="kc">true</span><span class="p">});</span> + <span class="p">});</span> +<span class="p">}</span> + +<span class="c1">//Random id generator</span> +<span class="kd">function</span> <span class="nx">randomid</span><span class="p">()</span> <span class="p">{</span> + <span class="k">return</span> <span class="k">new</span> <span class="nb">Date</span><span class="p">().</span><span class="nx">getTime</span><span class="p">().</span><span class="nx">toString</span><span class="p">()</span> <span class="o">+</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">random</span><span class="p">().</span><span class="nx">toString</span><span class="p">()</span> <span class="o">+</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">random</span><span class="p">().</span><span class="nx">toString</span><span class="p">();</span> +<span class="p">}</span> + +<span class="nx">app</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="s1">&#39;/upload&#39;</span><span class="p">,</span> <span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="kd">let</span> <span class="nx">img</span> <span class="o">=</span> <span class="nx">req</span><span class="p">.</span><span class="nx">files</span><span class="p">.</span><span class="nx">image</span><span class="p">;</span> + + <span class="kd">let</span> <span class="nx">id</span> <span class="o">=</span> <span class="nx">randomid</span><span class="p">();</span> + + <span class="c1">//Event listener that will fire when the proper randomid is provided</span> + <span class="nx">eventEmitter</span><span class="p">.</span><span class="nx">once</span><span class="p">(</span><span class="nx">id</span><span class="p">,</span> <span class="nx">msg</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="nx">res</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="nx">msg</span><span class="p">,</span> <span class="s1">&#39;binary&#39;</span><span class="p">);</span> + <span class="nx">res</span><span class="p">.</span><span class="nx">end</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="s1">&#39;binary&#39;</span><span class="p">);</span> + <span class="p">});</span> + + <span class="c1">//Checks if the queue exists, and create it if needed.</span> + <span class="nx">channel</span><span class="p">.</span><span class="nx">assertQueue</span><span class="p">(</span><span class="nx">QUEUE</span><span class="p">)</span> + <span class="c1">//Sent the buffered img to the queue with the ID and the responseQueue</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="nx">channel</span><span class="p">.</span><span class="nx">sendToQueue</span><span class="p">(</span><span class="nx">QUEUE</span><span class="p">,</span> <span class="nx">img</span><span class="p">.</span><span class="nx">data</span><span class="p">,</span> <span class="p">{</span><span class="nx">correlationId</span><span class="o">:</span><span class="nx">id</span><span class="p">,</span> <span class="nx">replyTo</span><span class="o">:</span> <span class="s1">&#39;amq.rabbitmq.reply-to&#39;</span><span class="p">}));</span> + +<span class="p">});</span> + +<span class="c1">//Finally start the app with the given port number</span> +<span class="c1">//now we initialize the rabbitmq connection before start the server</span> +<span class="nx">init</span><span class="p">()</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="nx">app</span><span class="p">.</span><span class="nx">listen</span><span class="p">(</span><span class="mi">4000</span><span class="p">,</span> <span class="p">()</span> <span class="p">=&gt;</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;Example app listening on port 4000!&#39;</span><span class="p">)))</span> + <span class="p">.</span><span class="k">catch</span><span class="p">(</span><span class="nx">err</span><span class="p">=&gt;</span><span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="nx">err</span><span class="p">));</span> +</pre></div> +<p>Ok, now we have our server code rewritten so let's see our worker code. Create a file named 'worker.js' and let's see how it's gonna be. It's really simple. You initialize a connection with RabbitMQ too, create a channel, check if the queue exists and start watching for incoming messages. When an image arrives, we do the job with it and send back to the &quot;replyTo&quot; queue the optimized image for the proper sender (correlationId). In the end, we do an acknowledge of the message so it get's out from the queue.</p> +<div class="highlight"><pre><span></span><span class="kr">const</span> <span class="nx">imagemin</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;imagemin&#39;</span><span class="p">);</span> +<span class="kr">const</span> <span class="nx">imageminPngquant</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;imagemin-pngquant&#39;</span><span class="p">);</span> + +<span class="kd">let</span> <span class="nx">channel</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span> +<span class="kr">const</span> <span class="nx">QUEUE</span> <span class="o">=</span> <span class="s1">&#39;imgqueue&#39;</span><span class="p">;</span> + +<span class="nx">require</span><span class="p">(</span><span class="s1">&#39;amqplib&#39;</span><span class="p">).</span><span class="nx">connect</span><span class="p">(</span><span class="s1">&#39;amqp://localhost&#39;</span><span class="p">)</span> +<span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">conn</span> <span class="p">=&gt;</span><span class="nx">conn</span><span class="p">.</span><span class="nx">createChannel</span><span class="p">())</span> +<span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">ch</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="nx">ch</span><span class="p">.</span><span class="nx">assertQueue</span><span class="p">(</span><span class="nx">QUEUE</span><span class="p">)</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="c1">//Watch incomming messages</span> + <span class="nx">ch</span><span class="p">.</span><span class="nx">consume</span><span class="p">(</span><span class="nx">QUEUE</span><span class="p">,</span> <span class="nx">msg</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="nx">imagemin</span><span class="p">.</span><span class="nx">buffer</span><span class="p">(</span><span class="nx">msg</span><span class="p">.</span><span class="nx">content</span><span class="p">,</span> <span class="p">{</span> + <span class="nx">plugins</span><span class="o">:</span> <span class="p">[</span><span class="nx">imageminPngquant</span><span class="p">()]</span> + <span class="p">})</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">out</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="c1">//Send back to the sender (replyTo) queue and give the correlationId back</span> + <span class="c1">//so we can emit the event.</span> + <span class="nx">ch</span><span class="p">.</span><span class="nx">sendToQueue</span><span class="p">(</span><span class="nx">msg</span><span class="p">.</span><span class="nx">properties</span><span class="p">.</span><span class="nx">replyTo</span><span class="p">,</span> <span class="nx">out</span><span class="p">,</span> <span class="p">{</span> + <span class="nx">correlationId</span><span class="o">:</span> <span class="nx">msg</span><span class="p">.</span><span class="nx">properties</span><span class="p">.</span><span class="nx">correlationId</span> + <span class="p">});</span> + + <span class="c1">//Acknowledge the job done with the message.</span> + <span class="nx">ch</span><span class="p">.</span><span class="nx">ack</span><span class="p">(</span><span class="nx">msg</span><span class="p">);</span> + <span class="p">});</span> + <span class="p">});</span> + <span class="p">});</span> +<span class="p">});</span> +</pre></div> +<p>The key points here are. Open just one connection to the hole server. You CAN create one channel for every request that you receive, but it can take some time if you have a really big cluster of RabbitMQ. It was a quick tutorial, but I hope that it was able to clear a few questions that you might have when working with rabbit and express.</p> +Microservices with NodeJS, Express.js and RabbitMQ Part 12018-04-04T11:25:00-03:002018-04-04T11:25:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-04-04:/en/microservices_nodejs_express_rabbitmq_part_1.html<p>This is the first part of a microservices development series. The service will consist of the bellow architecture, where we will expose an image optimizer service that will forward the request to a <a class="reference external" href="https://www.rabbitmq.com/">RabbitMQ</a> queue and answer with the bytecode of the optimized image. It shouldn't be a long series …</p><p>This is the first part of a microservices development series. The service will consist of the bellow architecture, where we will expose an image optimizer service that will forward the request to a <a class="reference external" href="https://www.rabbitmq.com/">RabbitMQ</a> queue and answer with the bytecode of the optimized image. It shouldn't be a long series so let's see what we can do.</p> +<img alt="Service architecture" src="/images/microservices_rabit_pt1.png" /> +<p>Let's get our environment working. First, we'll need to install the libraries that we'll use.</p> +<p>Create a dir and initialize the nodejs application inside it (<cite>npm init</cite>) and then let's install the deps.</p> +<ul class="simple"> +<li>amqplib - AMQP lib to interact with rabbitmq</li> +<li>express - Do our basic rest API</li> +<li>express-fileupload - easy file upload parser</li> +<li>imagemin and imagemin-pngquant - our image compacter</li> +</ul> +<div class="highlight"><pre><span></span>npm install --save express amqplib express-fileupload imagemin imagemin-pngquant +</pre></div> +<p>Now let's write the entry points for our service, we'll have two basic entry points. The path <cite>/</cite> that will have a welcome message, the second path will be <cite>/upload</cite> and this is the one that will handle the image and produce a job for our workers.</p> +<div class="highlight"><pre><span></span><span class="kr">const</span> <span class="nx">express</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;express&#39;</span><span class="p">);</span> +<span class="kr">const</span> <span class="nx">fileUpload</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;express-fileupload&#39;</span><span class="p">);</span> + +<span class="c1">//Instantiate the app and set the fileupload parser to manage files</span> +<span class="kr">const</span> <span class="nx">app</span> <span class="o">=</span> <span class="nx">express</span><span class="p">();</span> +<span class="nx">app</span><span class="p">.</span><span class="nx">use</span><span class="p">(</span><span class="nx">fileUpload</span><span class="p">());</span> + +<span class="c1">//Our index entry point</span> +<span class="nx">app</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;/&#39;</span><span class="p">,</span> <span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="nx">res</span><span class="p">.</span><span class="nx">send</span><span class="p">(</span><span class="s1">&#39;Hello From ImageCompacter service&#39;</span><span class="p">));</span> + +<span class="c1">//The path that will handle the image file and throw them to the queue</span> +<span class="nx">app</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="s1">&#39;/upload&#39;</span><span class="p">,</span> <span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="c1">//With express-fileupload we can grab the files like this</span> + <span class="kd">let</span> <span class="nx">img</span> <span class="o">=</span> <span class="nx">req</span><span class="p">.</span><span class="nx">files</span><span class="p">.</span><span class="nx">image</span><span class="p">;</span> <span class="c1">//&quot;image&quot; is the name of the input</span> + + <span class="nx">res</span><span class="p">.</span><span class="nx">send</span><span class="p">(</span><span class="s1">&#39;Not ready yet&#39;</span><span class="p">);</span> +<span class="p">});</span> + +<span class="c1">//Finally start the app with the given port number</span> +<span class="nx">app</span><span class="p">.</span><span class="nx">listen</span><span class="p">(</span><span class="mi">4000</span><span class="p">,</span> <span class="p">()</span> <span class="p">=&gt;</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;Example app listening on port 4000!&#39;</span><span class="p">));</span> +</pre></div> +<p>Let's check if it works, run the service with node.</p> +<div class="highlight"><pre><span></span>node index.js +Example app listening on port <span class="m">4000</span>! +</pre></div> +<p>Open the browser and check if it prints our hello message when accessing <cite>localhost:4000</cite>. Works? Greate. Now let's work with the image and see how we do it. To optimize our image, we'll use the library imagemin and <a class="reference external" href="https://www.npmjs.com/package/imagemin-pngquant">imagemin-pngquant</a>, it will be that simple for now, we'll work with rabbitmq latter.</p> +<div class="highlight"><pre><span></span><span class="kr">const</span> <span class="nx">imagemin</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;imagemin&#39;</span><span class="p">);</span> +<span class="kr">const</span> <span class="nx">imageminPngquant</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;imagemin-pngquant&#39;</span><span class="p">);</span> +<span class="c1">//...</span> + +<span class="c1">//The path that will handle the image file and throw them to the queue</span> +<span class="nx">app</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="s1">&#39;/upload&#39;</span><span class="p">,</span> <span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="kd">let</span> <span class="nx">img</span> <span class="o">=</span> <span class="nx">req</span><span class="p">.</span><span class="nx">files</span><span class="p">.</span><span class="nx">image</span><span class="p">;</span> <span class="c1">//&quot;image&quot; is the name of the input</span> + + <span class="nx">imagemin</span><span class="p">.</span><span class="nx">buffer</span><span class="p">(</span><span class="nx">img</span><span class="p">.</span><span class="nx">data</span><span class="p">,</span> <span class="p">{</span> + <span class="nx">plugins</span><span class="o">:</span> <span class="p">[</span><span class="nx">imageminPngquant</span><span class="p">()]</span> + <span class="p">})</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">out</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="nx">res</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="nx">out</span><span class="p">,</span><span class="s1">&#39;binary&#39;</span><span class="p">);</span> + <span class="nx">res</span><span class="p">.</span><span class="nx">end</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="s1">&#39;binary&#39;</span><span class="p">);</span> + <span class="p">});</span> +<span class="p">});</span> + + <span class="c1">//...</span> +</pre></div> +<p>Use <a class="reference external" href="https://www.getpostman.com/">Postman</a> to test the request. To see if it will work, make a request to <cite>http://localhost:4000/upload</cite> with a formdata with a file. Select the &quot;send and Download&quot; instead of &quot;Send&quot; and you should have an image after that. Bellow an image of how your postman should be.</p> +<img alt="Postman" src="/images/microservice_postman.png" /> +<p>That's it for today, next week we'll change our code to use RabbitMQ.</p> +Scaffolding a React app with Parcel and Yeoman2018-03-17T13:00:00-03:002018-03-17T13:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-03-17:/en/scaffolding_react_app_with_parcel_yeoman.html<p>Since <a class="reference external" href="https://parceljs.org/">Parcel JS</a> arrived, I've been using it a lot as an awesome alternative for WebPack. Webpack isn't bad but IMO it's too complex for the job and parcel do the same (at least the basic) with almost zero configuration. But if you need to create many apps (like a …</p><p>Since <a class="reference external" href="https://parceljs.org/">Parcel JS</a> arrived, I've been using it a lot as an awesome alternative for WebPack. Webpack isn't bad but IMO it's too complex for the job and parcel do the same (at least the basic) with almost zero configuration. But if you need to create many apps (like a react app) over and over again, it get's a lil boring following the basic steps.</p> +<div class="highlight"><pre><span></span>npm init -y +npm install --save react +npm install --save react-dom +npm install --save-dev parcel-bundler +npm install --save-dev babel-preset-env +npm install --save-dev babel-preset-react + +<span class="c1">#create .babelrc file</span> +<span class="c1">#create html, css, jsx files</span> + +parcel index.html +</pre></div> +<p>It's not a hard job, a simple shell script do the job, but what if you need some IFs when creating the app, or even change a few things at the <cite>package.json</cite>? A shell script still does the job, but come on... There is a better way. <a class="reference external" href="http://yeoman.io/">Yeoman</a> is here for you. I've already <a class="reference external" href="https://www.sipmann.com/en/desenvolvendo-app-firefoxos-pt.html">talked about it</a> on another post (Portuguese post).</p> +<p>Straight to the point, I've released a Yeoman generator to get the things a lil quicker. The name is <a class="reference external" href="https://www.npmjs.com/package/generator-parcel-react">generator-parcel-react</a> and it still lacks a few things that I will deal with soon. It's pretty simple to use it.</p> +<div class="highlight"><pre><span></span><span class="c1">#First time only</span> +npm install -g yo +npm install -g generator-parcel-react + +<span class="c1">#every time you create a new app</span> +yo parcel-react +</pre></div> +<p>And that's it. Right now you can scaffold and app with React, SASS and React Router. Hope you like it and feel free to ask new features.</p> + \ No newline at end of file diff --git a/en/feeds/front-end.atom.xml.gz b/en/feeds/front-end.atom.xml.gz new file mode 100644 index 000000000..7c5bfdd31 Binary files /dev/null and b/en/feeds/front-end.atom.xml.gz differ diff --git a/en/feeds/java.atom.xml b/en/feeds/java.atom.xml new file mode 100644 index 000000000..654c90584 --- /dev/null +++ b/en/feeds/java.atom.xml @@ -0,0 +1,89 @@ + +Sipmann - Javahttps://www.sipmann.com/en/2018-03-09T12:35:00-03:00Could not open connection with MySQL and Hibernate2018-03-09T12:35:00-03:002018-03-09T12:35:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-03-09:/en/cloud-not-open-connection-java-mysql-hibernate.html<p>Last day I decided to deploy a MySQL Docker image to work with my Java application. I've been using PostgreSQL instead and have no problems at all, but after I moved to MySQL, the app didn't connect anymore with the database and throw some &quot;Could not open connection&quot; at my …</p><p>Last day I decided to deploy a MySQL Docker image to work with my Java application. I've been using PostgreSQL instead and have no problems at all, but after I moved to MySQL, the app didn't connect anymore with the database and throw some &quot;Could not open connection&quot; at my face, but why? I've tried to connect to it manually and got the same problem.</p> +<p>After some research, I found that the true error should be java.sql.SQLException: null, message from server: &quot;Host '172.17.0.4' is not allowed to connect to this MySQL server&quot; but it wasn't showing to me...</p> +<p>After all, be aware that with the docker image MySQL:5.7.21 (latest version right now) the root user isn't allowed to remote connect to the database (it's alright, security reasons) and if you still want to do remote connections to it with root there are a few things you can do.</p> +<ol class="arabic simple"> +<li>Create a user or allow root to access from other IPs.</li> +</ol> +<div class="highlight"><pre><span></span><span class="o">#</span><span class="k">No</span> <span class="k">access</span> <span class="k">to</span> <span class="k">user</span> <span class="n">root</span> <span class="k">on</span> <span class="k">any</span> <span class="n">other</span> <span class="n">IP</span> +<span class="k">SELECT</span> <span class="k">User</span><span class="p">,</span> <span class="k">Host</span> <span class="k">FROM</span> <span class="n">mysql</span><span class="p">.</span><span class="k">user</span><span class="p">;</span> +<span class="o">+</span><span class="c1">---------------+-----------+</span> +<span class="o">|</span> <span class="k">User</span> <span class="o">|</span> <span class="k">Host</span> <span class="o">|</span> +<span class="o">+</span><span class="c1">---------------+-----------+</span> +<span class="o">|</span> <span class="n">healthchecker</span> <span class="o">|</span> <span class="n">localhost</span> <span class="o">|</span> +<span class="o">|</span> <span class="n">root</span> <span class="o">|</span> <span class="n">localhost</span> <span class="o">|</span> +<span class="o">+</span><span class="c1">---------------+-----------+</span> +<span class="mi">2</span> <span class="k">rows</span> <span class="k">in</span> <span class="k">set</span> <span class="p">(</span><span class="mi">0</span><span class="p">.</span><span class="mi">01</span> <span class="n">sec</span><span class="p">)</span> + +<span class="k">CREATE</span> <span class="k">USER</span> <span class="s1">&#39;newuser&#39;</span><span class="o">@</span><span class="s1">&#39;%&#39;</span> <span class="n">IDENTIFIED</span> <span class="k">BY</span> <span class="s1">&#39;password&#39;</span><span class="p">;</span> <span class="o">#%</span> <span class="n">mean</span> <span class="k">any</span> <span class="n">IP</span> +<span class="k">GRANT</span> <span class="k">ALL</span> <span class="k">PRIVILEGES</span> <span class="k">ON</span> <span class="o">*</span><span class="p">.</span><span class="o">*</span> <span class="k">TO</span> <span class="s1">&#39;newuser&#39;</span><span class="o">@</span><span class="s1">&#39;%&#39;</span><span class="p">;</span> <span class="o">#*</span><span class="p">.</span><span class="o">*</span> <span class="n">mean</span> <span class="k">database</span><span class="p">.</span><span class="k">table</span> <span class="p">;)</span> +</pre></div> +<ol class="arabic simple" start="2"> +<li>Use MariaDB instead, witch come (at least on the version 10.2.13) with root allowed to do remote connections and will work like MySQL :)</li> +</ol> +<p>I changed to <a class="reference external" href="https://mariadb.org/">MariaDB</a> as it work without creating user or any changes on the Java code or the <cite>docker run command</cite>.</p> +Solving java.net.SocketException: Protocol family unavailable on a Java + Docker + WildFly2018-03-04T17:40:00-03:002018-03-04T17:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-03-04:/en/socketException-protocol-family-unavailable-java-docker-wildfly.html<p>On the last days I've been playing with <a class="reference external" href="http://wildfly-swarm.io/">WildFly Swarm</a> and I decided to deploy a simple app with Docker. Should work fine, at least that was what I thought. Built a container with the following Dockerfile and instead of a working web app, all that I got was the …</p><p>On the last days I've been playing with <a class="reference external" href="http://wildfly-swarm.io/">WildFly Swarm</a> and I decided to deploy a simple app with Docker. Should work fine, at least that was what I thought. Built a container with the following Dockerfile and instead of a working web app, all that I got was the error <cite>java.net.SocketException: Protocol family unavailable</cite>.</p> +<div class="highlight"><pre><span></span><span class="k">FROM</span> <span class="s">java:openjdk-8-jdk</span> + +<span class="k">COPY</span> target/issues.jar /opt/issues.jar + +<span class="k">EXPOSE</span><span class="s"> 8080</span> + +<span class="k">CMD</span> <span class="p">[</span><span class="s2">&quot;java&quot;</span><span class="p">,</span><span class="s2">&quot;-jar&quot;</span><span class="p">,</span><span class="s2">&quot;/opt/issues.jar&quot;</span><span class="p">]</span> +</pre></div> +<p>For some reason, WildFly and Java decided to use the IPv6 network interface from Docker instead the v4, so all you have to do is tell Java to prefer IPv4 instead with the following configuration option in your pom.xml file inside your WildFly plugin.</p> +<div class="highlight"><pre><span></span><span class="nt">&lt;plugin&gt;</span> + <span class="nt">&lt;groupId&gt;</span>org.wildfly.swarm<span class="nt">&lt;/groupId&gt;</span> + <span class="nt">&lt;artifactId&gt;</span>wildfly-swarm-plugin<span class="nt">&lt;/artifactId&gt;</span> + <span class="nt">&lt;version&gt;</span>2018.2.0<span class="nt">&lt;/version&gt;</span> + + <span class="c">&lt;!-- ADD THIS --&gt;</span> + <span class="nt">&lt;configuration&gt;</span> + <span class="nt">&lt;mainClass&gt;</span>org.wildfly.swarm.examples.netflix.ribbon.frontend.Main<span class="nt">&lt;/mainClass&gt;</span> + <span class="nt">&lt;properties&gt;</span> + <span class="nt">&lt;java.net.preferIPv4Stack&gt;</span>true<span class="nt">&lt;/java.net.preferIPv4Stack&gt;</span> + <span class="nt">&lt;/properties&gt;</span> + <span class="nt">&lt;/configuration&gt;</span> +</pre></div> +<p>Another way to solve is adding the same properties to the run command at the Dockerfile, so you choose where you'll add it. Bellow the Dockerfile solution.</p> +<div class="highlight"><pre><span></span><span class="k">FROM</span> <span class="s">java:openjdk-8-jdk</span> +<span class="k">ENV</span> <span class="nv">JAVA_OPTS</span><span class="o">=</span><span class="s2">&quot;-Djava.net.preferIPv4Stack=true -Djava.net.preferIPv4Addresses=true&quot;</span> + +<span class="k">COPY</span> target/issues.jar /opt/issues.jar + +<span class="k">EXPOSE</span><span class="s"> 8080</span> + +<span class="k">ENTRYPOINT</span> <span class="nb">exec</span> java <span class="nv">$JAVA_OPTS</span> -jar /opt/issues.jar +</pre></div> +Java - Files.readAllBytes throws OutOfMemory2018-02-17T13:00:00-02:002018-02-17T13:00:00-02:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-02-17:/en/reading-files-java-readAllBytes-outofmemory.html<p>When you need to interact with files, there's the possibility to read all bytes from the file with <cite>Files.readAllBytes</cite>. But be aware of the kinds of files your application will deal with because the Java API files have a limit for the buffer that is defined as <cite>Integer.MAX_VALUE …</cite></p><p>When you need to interact with files, there's the possibility to read all bytes from the file with <cite>Files.readAllBytes</cite>. But be aware of the kinds of files your application will deal with because the Java API files have a limit for the buffer that is defined as <cite>Integer.MAX_VALUE</cite> as you can see above or at the OpenJDK sources.</p> +<div class="highlight"><pre><span></span><span class="kd">public</span> <span class="kd">static</span> <span class="kt">byte</span><span class="o">[]</span> <span class="nf">readAllBytes</span><span class="p">(</span><span class="n">Path</span> <span class="n">path</span><span class="p">)</span> <span class="kd">throws</span> <span class="n">IOException</span> <span class="p">{</span> + <span class="k">try</span> <span class="p">(</span><span class="n">FileChannel</span> <span class="n">fc</span> <span class="o">=</span> <span class="n">FileChannel</span><span class="p">.</span><span class="na">open</span><span class="p">(</span><span class="n">path</span><span class="p">))</span> <span class="p">{</span> + <span class="kt">long</span> <span class="n">size</span> <span class="o">=</span> <span class="n">fc</span><span class="p">.</span><span class="na">size</span><span class="p">();</span> + <span class="k">if</span> <span class="p">(</span><span class="n">size</span> <span class="o">&gt;</span> <span class="p">(</span><span class="kt">long</span><span class="p">)</span><span class="n">Integer</span><span class="p">.</span><span class="na">MAX_VALUE</span><span class="p">)</span> + <span class="k">throw</span> <span class="k">new</span> <span class="n">OutOfMemoryError</span><span class="p">(</span><span class="s">&quot;Required array size too large&quot;</span><span class="p">);</span> + + <span class="kt">byte</span><span class="o">[]</span> <span class="n">arr</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">byte</span><span class="o">[</span><span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">size</span><span class="o">]</span><span class="p">;</span> + <span class="n">ByteBuffer</span> <span class="n">bb</span> <span class="o">=</span> <span class="n">ByteBuffer</span><span class="p">.</span><span class="na">wrap</span><span class="p">(</span><span class="n">arr</span><span class="p">);</span> + <span class="k">while</span> <span class="p">(</span><span class="n">bb</span><span class="p">.</span><span class="na">hasRemaining</span><span class="p">())</span> <span class="p">{</span> + <span class="k">if</span> <span class="p">(</span><span class="n">fc</span><span class="p">.</span><span class="na">read</span><span class="p">(</span><span class="n">bb</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> + <span class="c1">// truncated</span> + <span class="k">break</span><span class="p">;</span> + <span class="p">}</span> + <span class="p">}</span> + + <span class="kt">int</span> <span class="n">nread</span> <span class="o">=</span> <span class="n">bb</span><span class="p">.</span><span class="na">position</span><span class="p">();</span> + <span class="k">return</span> <span class="p">(</span><span class="n">nread</span> <span class="o">==</span> <span class="n">size</span><span class="p">)</span> <span class="o">?</span> <span class="n">arr</span> <span class="p">:</span> <span class="n">Arrays</span><span class="p">.</span><span class="na">copyOf</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="n">nread</span><span class="p">);</span> + <span class="p">}</span> +<span class="p">}</span> +</pre></div> +<p>With that in mind, check if isn't better read chunks of bytes e work with that slice in exchange of loading the whole file into the memory ;). Above a simple example of how you can read chunks of bytes from the file.</p> +<div class="highlight"><pre><span></span><span class="kt">byte</span><span class="o">[]</span> <span class="n">buffer</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">byte</span><span class="o">[</span><span class="mi">1024</span><span class="o">]</span><span class="p">;</span> +<span class="n">FileInputStream</span> <span class="n">in</span> <span class="o">=</span> <span class="k">new</span> <span class="n">FileInputStream</span><span class="p">(</span><span class="n">file</span><span class="p">);</span> +<span class="kt">int</span> <span class="n">rc</span> <span class="o">=</span> <span class="n">in</span><span class="p">.</span><span class="na">read</span><span class="p">(</span><span class="n">buffer</span><span class="p">);</span> +<span class="k">while</span> <span class="p">(</span><span class="n">rc</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span> +<span class="p">{</span> + <span class="c1">//crazy stuff here with buffer</span> + <span class="n">rc</span> <span class="o">=</span> <span class="n">in</span><span class="p">.</span><span class="na">read</span><span class="p">(</span><span class="n">buffer</span><span class="p">);</span> +<span class="p">}</span> +</pre></div> + \ No newline at end of file diff --git a/en/feeds/java.atom.xml.gz b/en/feeds/java.atom.xml.gz new file mode 100644 index 000000000..d291607f9 Binary files /dev/null and b/en/feeds/java.atom.xml.gz differ diff --git a/en/feeds/linux.atom.xml b/en/feeds/linux.atom.xml new file mode 100644 index 000000000..7bc2622f6 --- /dev/null +++ b/en/feeds/linux.atom.xml @@ -0,0 +1,92 @@ + +Sipmann - Linuxhttps://www.sipmann.com/en/2020-10-20T19:00:00-03:00Zabbix Running on Low Memory Mode2020-10-20T19:00:00-03:002020-10-20T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-20:/en/zabbix-running-on-low-memory-mode.html<p>Hey folks, another Zabbix post today. This one it's about increasing the Zabbix Server Cache. It's pretty common (if you have the default settings only) get a warning about your <code>Zabbix value cache running on low memory mode</code> at your dashboard or logs.</p> +<p><img alt="Zabbix Dashboard warning about the memory problem" src="/images/zabbix_low_memory_mode.png"> +<img alt="Zabbix Dashboard cache graph 70% used" src="/images/zabbix_cache_filling.png"></p> +<p>To solve, go back to your Zabbix …</p><p>Hey folks, another Zabbix post today. This one it's about increasing the Zabbix Server Cache. It's pretty common (if you have the default settings only) get a warning about your <code>Zabbix value cache running on low memory mode</code> at your dashboard or logs.</p> +<p><img alt="Zabbix Dashboard warning about the memory problem" src="/images/zabbix_low_memory_mode.png"> +<img alt="Zabbix Dashboard cache graph 70% used" src="/images/zabbix_cache_filling.png"></p> +<p>To solve, go back to your Zabbix config file (<code>zabbix_server.conf</code>) and look for the tag <em>CacheSize</em>. Uncomment it and set to a value bigger than 8M (8M it's the default value). In my case, we set a cache of 100M. After the change, restart the service.</p> +<div class="highlight"><pre><span></span><code><span class="c1">### Option: CacheSize</span> +<span class="c1"># Size of configuration cache, in bytes.</span> +<span class="c1"># Shared memory size for storing host, item and trigger data.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 128K-64G</span> +<span class="c1"># Default:</span> +<span class="na">CacheSize</span><span class="o">=</span><span class="s">100M #uncomment this line</span> +</code></pre></div> + +<p><img alt="Zabbix Dashboard resolved memory problem" src="/images/zabbix_low_memory_solved.png"></p> +<p>See ya folks.</p>Zabbix poller processes more than 75%2020-07-02T19:00:00-03:002020-07-02T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-07-02:/en/zabbix-poller-processes-more-than-75.html<p>Hey folks, this is the third post about tweaking the Zabbix configurations. All changes that I've suggested here were based on a Zabbix Server with 50+ hosts. Another thing that can happen to your server, it's the poller get overwhelmed by the amount of servers that need to be polled …</p><p>Hey folks, this is the third post about tweaking the Zabbix configurations. All changes that I've suggested here were based on a Zabbix Server with 50+ hosts. Another thing that can happen to your server, it's the poller get overwhelmed by the amount of servers that need to be polled plus the ones that are not responding. Bellow two images where you can see the log and the graphic where you can see the usage percent. </p> +<p><img alt="Dashboard log about the poller processes" src="/images/zabbix_pooler.png"></p> +<p><img alt="Graph showing the utilization percent of each collector" src="/images/zabbix_pooler_3.png"></p> +<p>To solve, let's go back to the <code>zabbix_server.conf</code> file and find two variables, <code>StartPollers</code> and <code>StartPollersUnreachable</code>. Increase them as needed. There's no magic number, you must see what works for you. But keep in mind that the <code>StartPollersUnreachable</code> is responsible for that host that can't be "reached" (of course) and will hold your poller more time.</p> +<div class="highlight"><pre><span></span><code><span class="c1">### Option: StartPollers</span> +<span class="c1"># Number of pre-forked instances of pollers.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 0-1000</span> +<span class="c1"># Default:</span> +<span class="na">StartPollers</span><span class="o">=</span><span class="s">20</span> + +<span class="c1">#...</span> + +<span class="c1">### Option: StartPollersUnreachable</span> +<span class="c1"># Number of pre-forked instances of pollers for unreachable hosts (including IPMI and Java).</span> +<span class="c1"># At least one poller for unreachable hosts must be running if regular, IPMI or Java pollers</span> +<span class="c1"># are started.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 0-1000</span> +<span class="c1"># Default:</span> +<span class="na">StartPollersUnreachable</span><span class="o">=</span><span class="s">5</span> +</code></pre></div> + +<p>After the change, restart the server and wait a few moments and take a look again at your dashboard. Bellow the effect that I've got.</p> +<p><img alt="Graph showing the new utilization percent of the processes after the changes" src="/images/zabbix_pooler_4.png"></p>Zabbix ICMP pinger processes more than 75%2020-05-25T16:00:00-03:002020-05-25T16:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-05-25:/en/zabbix-icmp-pinger-processes-more-than-75.html<p>So your monitoring sytems have grown and your zabbix started loggin "Zabbix icmp pinger processes more than 75% busy" at the dashboard.</p> +<p><img alt="Dashboard do zabbix avisando sobre o erro" src="/images/zabbix_pinger01.png"></p> +<p>All you have to do is open your config file (<code>/etc/zabbix/zabbix_server.conf</code>) and find the a tag named <code>StartPingers</code>. It'll be commented by default. Uncomment it …</p><p>So your monitoring sytems have grown and your zabbix started loggin "Zabbix icmp pinger processes more than 75% busy" at the dashboard.</p> +<p><img alt="Dashboard do zabbix avisando sobre o erro" src="/images/zabbix_pinger01.png"></p> +<p>All you have to do is open your config file (<code>/etc/zabbix/zabbix_server.conf</code>) and find the a tag named <code>StartPingers</code>. It'll be commented by default. Uncomment it and set it's value to something like 3 or 4. It should solve your problem.</p> +<div class="highlight"><pre><span></span><code><span class="c1">### Option: StartPingers</span> +<span class="c1"># Number of pre-forked instances of ICMP pingers.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 0-1000</span> +<span class="c1"># Default:</span> +<span class="nv">StartPingers</span><span class="o">=</span><span class="m">4</span> +</code></pre></div> + +<h2>How many Pingers do I need?</h2> +<p>Well, there is no exact answer to this. If you set it too high, you'll be wasting resources. The best way to solve, it's increasing them as soon as you notice the percentage growing.</p>Zabbix Server Out of Memory2020-02-27T19:00:00-03:002020-02-27T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-02-27:/en/zabbix-server-out-of-memory-crash.html<p>Do you have a crashing Zabbix Server and looking through the log <code>/var/log/zabbix/zabbix_server.log</code> you see the following out of memory message?</p> +<div class="highlight"><pre><span></span><code>__mem_malloc: skipped <span class="m">0</span> asked <span class="m">24</span> skip_min <span class="m">18446744073709551615</span> skip_max <span class="m">0</span> +<span class="o">[</span>file:dbconfig.c,line:94<span class="o">]</span> __zbx_mem_realloc<span class="o">()</span>: out of memory <span class="o">(</span>requested <span class="m">16</span> bytes<span class="o">)</span> +<span class="o">[</span>file:dbconfig.c,line …</code></pre></div><p>Do you have a crashing Zabbix Server and looking through the log <code>/var/log/zabbix/zabbix_server.log</code> you see the following out of memory message?</p> +<div class="highlight"><pre><span></span><code>__mem_malloc: skipped <span class="m">0</span> asked <span class="m">24</span> skip_min <span class="m">18446744073709551615</span> skip_max <span class="m">0</span> +<span class="o">[</span>file:dbconfig.c,line:94<span class="o">]</span> __zbx_mem_realloc<span class="o">()</span>: out of memory <span class="o">(</span>requested <span class="m">16</span> bytes<span class="o">)</span> +<span class="o">[</span>file:dbconfig.c,line:94<span class="o">]</span> __zbx_mem_realloc<span class="o">()</span>: please increase CacheSize configuration parameter +</code></pre></div> + +<p>Besides the clear solution to the error, that's a common issue on servers that have a few monitoring items on it (servers, switches, firewalls, databases, etc...). To solve, go to your zabbix_server.conf and look for the CacheSize property and set it to a higher value. Its default should be 8M. At a customer that has somewhere between 4 servers, 7 firewalls/appliances, and a few other things, a 32M did the job, but you can set up to 8G.</p> +<p>See ya folks.</p>Connecting to a database through SSH2018-03-29T10:03:00-03:002018-03-29T10:03:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-03-29:/en/connecting_to_database_through_ssh.html<p>If someday, for some reason, you need to establish a connection with a database which is behind a firewall and you only have SSH access on that server (and you don't want to use a CLI) you can do an SSH tunnel. It's pretty simple, bellow has a sample of …</p><p>If someday, for some reason, you need to establish a connection with a database which is behind a firewall and you only have SSH access on that server (and you don't want to use a CLI) you can do an SSH tunnel. It's pretty simple, bellow has a sample of how to allow connections to a remote Firebird database.</p> +<div class="highlight"><pre><span></span>ssh -L <span class="m">3051</span>:192.168.1.9:3050 username@192.168.1.9 +</pre></div> +<p>The <cite>-L</cite> parameter tells to SSH do a local port forwarding on local port <cite>3051</cite> to remote port <cite>3050</cite>. You can use it to a connection with many services, not just databases.</p> +<p>You can do the reverse kind of tunnel, forward connections from the host to your local machine, you just have to change the parameter form &quot;-L&quot; to &quot;-R&quot; and the port order is inverted, first come the port where the server will listen and after your localhost port. This remote port forwarding must be enabled on the server. Look for <cite>GatewayPorts</cite> at the ssh config file.</p> +<div class="highlight"><pre><span></span>ssh -R <span class="m">3050</span>:localhost:3050 username@192.168.1.9 +</pre></div> +<p>Why whould you need something like that?? Let's say you want to share a localhost site/database with a friend, but your internet connection don't allow you to expose any port but you have access to a remote server witch can do that. Problem solved ;).</p> +Change display settings on linux with Disper2018-02-27T12:40:00-03:002018-02-27T12:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-02-27:/en/linux-external-display-with-disper.html<p>From time to time, I change the Linux distro on my laptop or just do a fresh install on it. And once in a while, have random problems with external displays. It can be something really &quot;simple&quot; like don't detecting the external monitor or something crazy like the image below …</p><p>From time to time, I change the Linux distro on my laptop or just do a fresh install on it. And once in a while, have random problems with external displays. It can be something really &quot;simple&quot; like don't detecting the external monitor or something crazy like the image below.</p> +<img alt="Display bug" src="/images/bug.png" /> +<p>As you can see at the image, the mint detected the display but mirrored it in a crazy way that works but doesn't at the same time. If you try anything and doesn't get working, or just wanna skip the whole job of configuring complexes text files, give a try to <a class="reference external" href="http://willem.engen.nl/projects/disper/">Disper</a>. Download the latest version. +Extract it on any folder, and make install it (on the extracted folder).</p> +<div class="highlight"><pre><span></span>make install +</pre></div> +<p>After that, you can start using it... There are a few options that will serve you well.</p> +<div class="highlight"><pre><span></span>disper -e <span class="c1">#extend your display</span> +</pre></div> +<div class="highlight"><pre><span></span>disper -c <span class="c1">#clone your display</span> +</pre></div> +<div class="highlight"><pre><span></span>disper -s <span class="c1">#only your external display</span> +</pre></div> + \ No newline at end of file diff --git a/en/feeds/linux.atom.xml.gz b/en/feeds/linux.atom.xml.gz new file mode 100644 index 000000000..4bf810b98 Binary files /dev/null and b/en/feeds/linux.atom.xml.gz differ diff --git a/en/feeds/mauricio-camargo-sipmann.atom.xml b/en/feeds/mauricio-camargo-sipmann.atom.xml new file mode 100644 index 000000000..98bb900e9 --- /dev/null +++ b/en/feeds/mauricio-camargo-sipmann.atom.xml @@ -0,0 +1,813 @@ + +Sipmann - Maurício Camargo Sipmannhttps://www.sipmann.com/en/2020-12-21T13:30:00-03:00Monitoring MySQL restarts with PowerShell2020-12-21T13:30:00-03:002020-12-21T13:30:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-12-21:/en/monitoring-mysql-restarts-with-powershell.html<p>Hey folks, it's time for another PowerShell script. If you haven't seen the other ones, check the links below.</p> +<ul> +<li><a href="https://www.sipmann.com/en/monitoring-mysql-replication-with-powershell.html">Monitoring MySQL replication with PowerShell</a></li> +</ul> +<p>Well, this one it's a pretty simple script, but again, if your customer doesn't have a Zabbix server or doesn't allow you to setup one to …</p><p>Hey folks, it's time for another PowerShell script. If you haven't seen the other ones, check the links below.</p> +<ul> +<li><a href="https://www.sipmann.com/en/monitoring-mysql-replication-with-powershell.html">Monitoring MySQL replication with PowerShell</a></li> +</ul> +<p>Well, this one it's a pretty simple script, but again, if your customer doesn't have a Zabbix server or doesn't allow you to setup one to do the monitoring, a set of scripts can be handy. We start executing some basic query <code>SHOW GLOBAL STATUS LIKE 'Uptime'</code>, with that we'll get exactly what we're looking for.</p> +<p>If for some reason, the command fails (watch for the "global" variable called <code>$lastExitCode</code>), we send an e-mail telling you about that connection problem.</p> +<p>And then, we get to the part where we parse the value, this one is pretty similar to the parse we did on the first post about using PowerShell to monitor MySQL. But we basically look for the Value line, split it by space and then parse the second position to an integer. And then all we have to do is check if the uptime is lower than our threshold, if it is we send an e-mail.</p> +<div class="highlight"><pre><span></span><code><span class="nv">$MailFrom</span> <span class="p">=</span> <span class="s1">&#39;maurio[at]sipmann.com&#39;</span> +<span class="nv">$MailTo</span> <span class="p">=</span> <span class="s1">&#39;mauricio[at]sipmann.com&#39;</span> +<span class="nv">$MysqlHost</span> <span class="p">=</span> <span class="s1">&#39;127.0.0.1&#39;</span> +<span class="nv">$MysqlUser</span> <span class="p">=</span> <span class="s1">&#39;root&#39;</span> +<span class="nv">$MysqlPass</span> <span class="p">=</span> <span class="s1">&#39;123&#39;</span> + + +<span class="nv">$data</span> <span class="p">=</span> <span class="p">$(</span><span class="n">mysql</span> <span class="n">-h</span> <span class="nv">$MysqlHost</span> <span class="n">-u</span> <span class="nv">$MysqlUser</span> <span class="n">-p</span><span class="s2">&quot;$MysqlPass&quot;</span> <span class="n">-e</span> <span class="s2">&quot;SHOW GLOBAL STATUS LIKE &#39;Uptime&#39; \G&quot;</span><span class="p">)</span> + +<span class="cm">&lt;# Unable to execute the sql Command #&gt;</span> +<span class="k">if</span> <span class="p">(</span><span class="nv">$lastExitCode</span> <span class="o">-eq</span> <span class="n">1</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Send-MailMessage</span> <span class="n">-To</span> <span class="nv">$MailTo</span> <span class="n">-From</span> <span class="nv">$MailFrom</span> <span class="n">-Subject</span> <span class="s1">&#39;Connection problem&#39;</span> <span class="n">-bodyAsHtml</span> <span class="s2">&quot;Connection problem on host ${MysqlHost}&quot;</span> <span class="n">-Credential</span> <span class="nb">Get-Credential</span> <span class="n">-SmtpServer</span> <span class="s1">&#39;smtp.office365.com&#39;</span> <span class="n">-Port</span> <span class="n">587</span> <span class="n">-UseSsl</span> + <span class="n">exit</span> +<span class="p">}</span> + +<span class="nv">$UpTime</span> <span class="p">=</span> <span class="no">[int]</span><span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Value:&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> + +<span class="cm">&lt;# If the uptime is lower then 20 minutes #&gt;</span> +<span class="k">if</span> <span class="p">(</span><span class="nv">$UpTime</span> <span class="o">-lt</span> <span class="n">1200</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Send-MailMessage</span> <span class="n">-To</span> <span class="nv">$MailTo</span> <span class="n">-From</span> <span class="nv">$MailFrom</span> <span class="n">-Subject</span> <span class="s2">&quot;MySQL Restarted&quot;</span> <span class="n">-bodyAsHtml</span> <span class="s2">&quot;MySQL host ${MysqlHost} restarted less than 20 minutes ago&quot;</span> <span class="n">-Credential</span> <span class="nb">Get-Credential</span> <span class="n">-SmtpServer</span> <span class="s1">&#39;smtp.office365.com&#39;</span> <span class="n">-Port</span> <span class="n">587</span> <span class="n">-UseSsl</span> +<span class="p">}</span> +</code></pre></div> + +<p>This script (and the other ones I use) is available at my GitHub <a href="https://github.com/sipmann/PowerShellScripts">here</a>. Keep in mind that the ones on the GitHub repo, are a little different from here.</p>Changing a MySQL user password across multiple application instances without downtime2020-12-09T13:40:00-03:002020-12-09T13:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-12-09:/en/mysql-dual-password-functionality.html<p>Do you need to change the password of a MySQL user that it's being used in an application, and can't allow a single downtime? Well, MySQL 8.0.14 came with a feature called <a href="https://dev.mysql.com/doc/refman/8.0/en/password-management.html#dual-passwords">Dual Password Support</a>, with it you can change the password keeping the previous password as a …</p><p>Do you need to change the password of a MySQL user that it's being used in an application, and can't allow a single downtime? Well, MySQL 8.0.14 came with a feature called <a href="https://dev.mysql.com/doc/refman/8.0/en/password-management.html#dual-passwords">Dual Password Support</a>, with it you can change the password keeping the previous password as a kind of backup. That way you still can log in using the old password or can start using the new one. With that, the password change workflow it's the following.</p> +<p>1) Change password keeping the old one;</p> +<p>2) Deploy the new config to your app/cluster;</p> +<p>3) Discard the old password.</p> +<p>To change the password and keep the old one, you have the following command.</p> +<div class="highlight"><pre><span></span><code><span class="k">ALTER</span> <span class="n">USER</span> <span class="s1">&#39;appuser&#39;</span><span class="o">@</span><span class="s1">&#39;localhost&#39;</span> <span class="n">IDENTIFIED</span> <span class="k">BY</span> <span class="s1">&#39;new_password&#39;</span> <span class="n">RETAIN</span> <span class="n">CURRENT</span> <span class="n">PASSWORD</span><span class="p">;</span> +</code></pre></div> + +<p>To discard the old one, run the following.</p> +<div class="highlight"><pre><span></span><code><span class="k">ALTER</span> <span class="n">USER</span> <span class="s1">&#39;appuser&#39;</span><span class="o">@</span><span class="s1">&#39;localhost&#39;</span> <span class="n">DISCARD</span> <span class="n">OLD</span> <span class="n">PASSWORD</span><span class="p">;</span> +</code></pre></div> + +<p>And you are done. Hope you find it as useful as I :)</p>Apache Nifi JSON to SQL Replacing underscore2020-12-02T14:00:00-03:002020-12-02T14:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-12-02:/en/apache-nifi-json-to-sql-replacing-underscore.html<p>Recently I was doing some ETL with Apache NiFi. But after a few minutes of drawing my flow, I saw that the component ConvertJSONToSQL was replacing the underscore ('_') from the field name in the where condition (I was preparing an Update SQL). That was weird because, at the set …</p><p>Recently I was doing some ETL with Apache NiFi. But after a few minutes of drawing my flow, I saw that the component ConvertJSONToSQL was replacing the underscore ('_') from the field name in the where condition (I was preparing an Update SQL). That was weird because, at the set statement, the field name was kept intact. After some research, I found that the property (see bellow) <code>Translate Field Names</code> was responsible for that weird replacement.</p> +<p><img alt="Apache NiFi JSONToSQL config" src="/images/apache_nifi_jsontosql.png"></p> +<p>Before setting it to <strong>FALSE</strong>, be aware that the properties on your JSON data must match exactly the name of your fields.</p>Blocking a user on SQL Server based on a schedule2020-11-14T07:00:00-03:002020-11-14T07:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-11-14:/en/blocking-user-on-sql-server-based-on-schedule.html<p>Ok, some time ago, I've posted about how you can set limits to connections on SQL Server using the <a href="https://www.sipmann.com/limiting-connection-resources-sql-server.html#.X6Cz8IhKhPY">Resource Governor</a>. But what if you can't use it? You always can block logins using a login trigger, but I don't like the idea of having selects running on every login …</p><p>Ok, some time ago, I've posted about how you can set limits to connections on SQL Server using the <a href="https://www.sipmann.com/limiting-connection-resources-sql-server.html#.X6Cz8IhKhPY">Resource Governor</a>. But what if you can't use it? You always can block logins using a login trigger, but I don't like the idea of having selects running on every login. So I came across with a solution using a stored procedure, a table and the Agent.</p> +<p>The main idea is, store the time that a user must be blocked and using the Agent, disable or enable the user. Bellow you can see the table (the table is in Portuguese, but I have a few comment blocks to help you).</p> +<div class="highlight"><pre><span></span><code><span class="k">CREATE</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"> </span><span class="p">(</span><span class="w"></span> +<span class="w"> </span><span class="n">Id</span><span class="w"> </span><span class="nc">INT</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">LoginName</span><span class="w"> </span><span class="nc">NVARCHAR</span><span class="p">(</span><span class="mi">100</span><span class="p">)</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">HrInicio</span><span class="w"> </span><span class="nc">TIME</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"> </span><span class="cm">/* Startint block time */</span><span class="w"></span> +<span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="nc">TIME</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"> </span><span class="cm">/* Ending block time */</span><span class="w"></span> +<span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="nc">INT</span><span class="w"> </span><span class="k">DEFAULT</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="cm">/* 0 = unblocked, 1 = blocked */</span><span class="w"></span> +<span class="w"> </span><span class="k">PRIMARY</span><span class="w"> </span><span class="k">KEY</span><span class="w"> </span><span class="p">(</span><span class="n">Id</span><span class="p">)</span><span class="w"></span> +<span class="p">);</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> + +<span class="cm">/* Don&#39;t block the SA user, precautions, you know */</span><span class="w"></span> +<span class="k">ALTER</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"></span> +<span class="w"> </span><span class="k">ADD</span><span class="w"> </span><span class="k">CONSTRAINT</span><span class="w"> </span><span class="n">chk_users</span><span class="w"> </span><span class="k">CHECK</span><span class="w"> </span><span class="p">(</span><span class="n">LoginName</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;sa&#39;</span><span class="p">));</span><span class="w"></span> + +<span class="k">ALTER</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"></span> +<span class="w"> </span><span class="k">ADD</span><span class="w"> </span><span class="k">CONSTRAINT</span><span class="w"> </span><span class="n">chk_hora_final_maior</span><span class="w"> </span><span class="k">CHECK</span><span class="w"> </span><span class="p">(</span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="n">HrInicio</span><span class="p">);</span><span class="w"></span> + +<span class="k">ALTER</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"></span> +<span class="w"> </span><span class="k">ADD</span><span class="w"> </span><span class="k">CONSTRAINT</span><span class="w"> </span><span class="n">chk_status_bloqueio</span><span class="w"> </span><span class="k">CHECK</span><span class="w"> </span><span class="p">(</span><span class="n">Bloqueado</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">));</span><span class="w"></span> + +<span class="k">CREATE</span><span class="w"> </span><span class="k">SEQUENCE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">seq_HorariosBloqueio</span><span class="w"> </span><span class="k">START</span><span class="w"> </span><span class="k">WITH</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="n">INCREMENT</span><span class="w"> </span><span class="k">BY</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +</code></pre></div> + +<p>After creating the table, let's check the procedure that will handle the enabling/disabling the users. Be aware that on the procedure, I've set the database name where the table was stored, you can change it replacing the <code>DBATOOLS</code> text to the database name where you created the table.</p> +<div class="highlight"><pre><span></span><code><span class="k">IF</span><span class="w"> </span><span class="nf">OBJECT_ID</span><span class="p">(</span><span class="s1">&#39;dbo.sp_ValidarLogin&#39;</span><span class="p">)</span><span class="w"> </span><span class="k">IS</span><span class="w"> </span><span class="k">NULL</span><span class="w"></span> +<span class="w"> </span><span class="k">EXEC</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;CREATE PROCEDURE dbo.sp_ValidarLogin AS RETURN 0;&#39;</span><span class="p">);</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> + +<span class="k">CREATE</span><span class="w"> </span><span class="ow">OR</span><span class="w"> </span><span class="k">ALTER</span><span class="w"> </span><span class="k">PROC</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">sp_ValidarLogin</span><span class="w"></span> +<span class="k">AS</span><span class="w"> </span><span class="k">BEGIN</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="nc">NVARCHAR</span><span class="p">(</span><span class="mi">100</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="nc">TIME</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="k">SET</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nf">CAST</span><span class="p">(</span><span class="nf">GETDATE</span><span class="p">()</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="nc">TIME</span><span class="p">);</span><span class="w"></span> + +<span class="w"> </span><span class="cm">/* Block the ones that aren&#39;t blocked already and maches the time */</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="n">block_cursor</span><span class="w"> </span><span class="nc">CURSOR</span><span class="w"></span> +<span class="w"> </span><span class="k">FOR</span><span class="w"> </span><span class="k">SELECT</span><span class="w"> </span><span class="n">LoginName</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&lt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&gt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"></span> +<span class="w"> </span><span class="k">OPEN</span><span class="w"> </span><span class="n">block_cursor</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">block_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> + +<span class="w"> </span><span class="k">WHILE</span><span class="w"> </span><span class="nb">@@FETCH_STATUS</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"></span> +<span class="w"> </span><span class="k">BEGIN</span><span class="w"></span> +<span class="w"> </span><span class="k">exec</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;ALTER LOGIN &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="s1">&#39; DISABLE;&#39;</span><span class="p">);</span><span class="w"></span> + +<span class="w"> </span><span class="k">print</span><span class="w"> </span><span class="s1">&#39;Bloqued usuario &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">block_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> +<span class="w"> </span><span class="k">END</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">CLOSE</span><span class="w"> </span><span class="n">block_cursor</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="k">DEALLOCATE</span><span class="w"> </span><span class="n">block_cursor</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">UPDATE</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">SET</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&lt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&gt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"></span> + + +<span class="w"> </span><span class="cm">/* Enable up who was blocked */</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="nc">CURSOR</span><span class="w"></span> +<span class="w"> </span><span class="k">FOR</span><span class="w"> </span><span class="k">SELECT</span><span class="w"> </span><span class="n">LoginName</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="p">(</span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">OR</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="p">)</span><span class="w"></span> +<span class="w"> </span><span class="k">OPEN</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> + +<span class="w"> </span><span class="k">WHILE</span><span class="w"> </span><span class="nb">@@FETCH_STATUS</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"></span> +<span class="w"> </span><span class="k">BEGIN</span><span class="w"></span> +<span class="w"> </span><span class="k">exec</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;ALTER LOGIN &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"> </span><span class="o">+</span><span class="s1">&#39; ENABLE;&#39;</span><span class="p">);</span><span class="w"></span> + +<span class="w"> </span><span class="k">print</span><span class="w"> </span><span class="s1">&#39;Unbloqued usuario &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> +<span class="w"> </span><span class="k">END</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">CLOSE</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="k">DEALLOCATE</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">UPDATE</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">SET</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="p">(</span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">OR</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="p">)</span><span class="w"></span> +<span class="k">END</span><span class="p">;</span><span class="w"></span> +</code></pre></div> + +<p>Ok, so now all you have to do, is schedule a job to run that stored procedure from minute to minute. Again, the main idea is tell the procedure when a user must be blocked and when it'll be unblocked. </p> +<div class="highlight"><pre><span></span><code><span class="err"> -- Will block the user protheus from 10 AM till 15 PM</span> +<span class="err"> INSERT INTO dbo.HorariosBloqueio (Id, LoginName, HrInicio, HrTermino) VALUES (NEXT VALUE FOR seq_HorariosBloqueio, &#39;protheus&#39;, &#39;10:00:00&#39;, &#39;15:00:00&#39;);</span> +</code></pre></div>How to set columns on select using Entity Framework2020-10-28T19:00:00-03:002020-10-28T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-28:/en/select_specific_fields_with_efcore.html<p>So, you use Entity Framework Core, and you usually code your selects like the following, maybe you are getting too much data.</p> +<div class="highlight"><pre><span></span><code><span class="kt">var</span> <span class="n">products</span> <span class="p">=</span> <span class="n">Products</span> + <span class="p">.</span><span class="n">Where</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span> <span class="p">&gt;</span> <span class="m">0</span><span class="p">)</span> + <span class="p">.</span><span class="n">OrderBy</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">)</span> + <span class="p">.</span><span class="n">ToList</span><span class="p">()</span> +</code></pre></div> + +<p>Running the query above, on my table, you'll get the following output, take a look …</p><p>So, you use Entity Framework Core, and you usually code your selects like the following, maybe you are getting too much data.</p> +<div class="highlight"><pre><span></span><code><span class="kt">var</span> <span class="n">products</span> <span class="p">=</span> <span class="n">Products</span> + <span class="p">.</span><span class="n">Where</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span> <span class="p">&gt;</span> <span class="m">0</span><span class="p">)</span> + <span class="p">.</span><span class="n">OrderBy</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">)</span> + <span class="p">.</span><span class="n">ToList</span><span class="p">()</span> +</code></pre></div> + +<p>Running the query above, on my table, you'll get the following output, take a look at how many columns you are getting back from your database.</p> +<p><img alt="Screenshot with every single column" src="/images/ef_core_allcolumns.png"></p> +<p>In my case, I only care about the Title, PublishedData, and a small description. So to get back only these fields, we have a few options. In the first one, we'll set the fields and return them as a dynamic object, the second one, is to give the .NET a class to use. </p> +<div class="highlight"><pre><span></span><code><span class="kt">var</span> <span class="n">products</span> <span class="p">=</span> <span class="n">Products</span> + + <span class="p">.</span><span class="n">Select</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="k">new</span> <span class="p">{</span><span class="n">p</span><span class="p">.</span><span class="n">ProductID</span><span class="p">,</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">,</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span><span class="p">,</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitPrice</span><span class="p">})</span> + <span class="c1">//.Select(p =&gt; new ProductDTO {p.ProductID, p.ProductName, p.UnitsInStock, p.UnitPrice})</span> + + <span class="p">.</span><span class="n">Where</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span> <span class="p">&gt;</span> <span class="m">0</span><span class="p">)</span> + <span class="p">.</span><span class="n">OrderBy</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">)</span> + <span class="p">.</span><span class="n">ToList</span><span class="p">()</span> +</code></pre></div> + +<p><img alt="Screenshot with fewer columns and also fewer data size" src="/images/ef_core_less_columns.png"></p>Zabbix Running on Low Memory Mode2020-10-20T19:00:00-03:002020-10-20T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-20:/en/zabbix-running-on-low-memory-mode.html<p>Hey folks, another Zabbix post today. This one it's about increasing the Zabbix Server Cache. It's pretty common (if you have the default settings only) get a warning about your <code>Zabbix value cache running on low memory mode</code> at your dashboard or logs.</p> +<p><img alt="Zabbix Dashboard warning about the memory problem" src="/images/zabbix_low_memory_mode.png"> +<img alt="Zabbix Dashboard cache graph 70% used" src="/images/zabbix_cache_filling.png"></p> +<p>To solve, go back to your Zabbix …</p><p>Hey folks, another Zabbix post today. This one it's about increasing the Zabbix Server Cache. It's pretty common (if you have the default settings only) get a warning about your <code>Zabbix value cache running on low memory mode</code> at your dashboard or logs.</p> +<p><img alt="Zabbix Dashboard warning about the memory problem" src="/images/zabbix_low_memory_mode.png"> +<img alt="Zabbix Dashboard cache graph 70% used" src="/images/zabbix_cache_filling.png"></p> +<p>To solve, go back to your Zabbix config file (<code>zabbix_server.conf</code>) and look for the tag <em>CacheSize</em>. Uncomment it and set to a value bigger than 8M (8M it's the default value). In my case, we set a cache of 100M. After the change, restart the service.</p> +<div class="highlight"><pre><span></span><code><span class="c1">### Option: CacheSize</span> +<span class="c1"># Size of configuration cache, in bytes.</span> +<span class="c1"># Shared memory size for storing host, item and trigger data.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 128K-64G</span> +<span class="c1"># Default:</span> +<span class="na">CacheSize</span><span class="o">=</span><span class="s">100M #uncomment this line</span> +</code></pre></div> + +<p><img alt="Zabbix Dashboard resolved memory problem" src="/images/zabbix_low_memory_solved.png"></p> +<p>See ya folks.</p>Monitoring MySQL Replication Status with PowerShell2020-10-14T19:00:00-03:002020-10-14T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-14:/en/monitoring-mysql-replication-with-powershell.html<p>I've been migration some bash scripts that I have to PowerShell, and it's time to migrate a script that monitors the replication of a MySQL database. The credit for the original script goes to <a href="https://handyman.dulare.com/mysql-replication-status-alerts-with-bash-script/">Paweł</a>. It's a simple script where I seek a few tags/fields that we get from …</p><p>I've been migration some bash scripts that I have to PowerShell, and it's time to migrate a script that monitors the replication of a MySQL database. The credit for the original script goes to <a href="https://handyman.dulare.com/mysql-replication-status-alerts-with-bash-script/">Paweł</a>. It's a simple script where I seek a few tags/fields that we get from <code>SHOW SLAVE STATUS\G</code> command, the fields are. <code>Slave_IO_Running</code>, <code>Slave_SQL_Running</code>, and <code>Seconds_Behind_Master</code>. I still need to figure out the proper way to store/read variables like usernames and passwords, if you have any tips, feel free to even make a pull request (<a href="https://github.com/sipmann/PowerShellScripts">here</a>) at the git where I'll store some scripts.</p> +<div class="highlight"><pre><span></span><code><span class="cm">&lt;#</span> +<span class="cm"> Variables definition</span> +<span class="cm">#&gt;</span> +<span class="nv">$MaxSeconds</span> <span class="p">=</span> <span class="n">120</span> <span class="c"># Max seconds behind master allowed</span> +<span class="nv">$MysqlUser</span> <span class="p">=</span> <span class="s1">&#39;root&#39;</span> +<span class="nv">$MysqlPass</span> <span class="p">=</span> <span class="s1">&#39;&#39;</span> + +<span class="nv">$MailTo</span> <span class="p">=</span> <span class="s1">&#39;mauricio@sipmann.com&#39;</span> +<span class="nv">$MailFrom</span> <span class="p">=</span> <span class="s1">&#39;mauricio@sipmann.com&#39;</span> + + +<span class="nv">$data</span> <span class="p">=</span> <span class="p">$(</span><span class="n">mysql</span> <span class="n">-u</span> <span class="nv">$MysqlUser</span> <span class="n">-p</span><span class="s2">&quot;$MysqlPass&quot;</span> <span class="n">-e</span> <span class="s1">&#39;SHOW SLAVE STATUS \G&#39;</span><span class="p">)</span> + +<span class="c">#Debug data</span> +<span class="c">#$data = Get-Content &#39;c:\temp\sampleresult.txt&#39;</span> + +<span class="cm">&lt;# Parse the data #&gt;</span> +<span class="nv">$IORunning</span> <span class="p">=</span> <span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Slave_IO_Running:&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> +<span class="nv">$SQLRunning</span> <span class="p">=</span> <span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Slave_SQL_Running:&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> +<span class="nv">$LastErrNo</span> <span class="p">=</span> <span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Last_Errno&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> +<span class="nv">$SecondsBh</span> <span class="p">=</span> <span class="no">[int]</span><span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Seconds_Behind_Master&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> + +<span class="k">If</span> <span class="p">(</span><span class="nv">$IORunning</span> <span class="o">-Eq</span> <span class="s1">&#39;No&#39;</span> <span class="o">-Or</span> <span class="nv">$SQLRunning</span> <span class="o">-Eq</span> <span class="s1">&#39;No&#39;</span> <span class="o">-Or</span> <span class="nv">$SecondsBh</span> <span class="o">-gt</span> <span class="nv">$MaxSeconds</span><span class="p">)</span> <span class="p">{</span> + <span class="nv">$MailBody</span> <span class="p">=</span> <span class="s1">&#39;&lt;h1&gt;Problema na replicação&lt;/h1&gt;&lt;br&gt;&#39;</span> + + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39; IO Running: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$IORunning</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39; SQL Running: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$SQLRunning</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39;Seconds Behind: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$SecondsBh</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39; Last Err No: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$LastErrNo</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + + <span class="cm">&lt;# Send e-mail, maybe some telegram message here too #&gt;</span> + <span class="nb">Send-MailMessage</span> <span class="n">-To</span> <span class="nv">$MailTo</span> <span class="n">-From</span> <span class="nv">$MailFrom</span> <span class="n">-Subject</span> <span class="s1">&#39;Problemas na replicação&#39;</span> <span class="n">-bodyAsHtml</span> <span class="nv">$MailBody</span> <span class="n">-Credential</span> <span class="p">(</span><span class="nb">Get-Credential</span><span class="p">)</span> <span class="n">-SmtpServer</span> <span class="s1">&#39;smtp.office365.com&#39;</span> <span class="n">-Port</span> <span class="n">587</span> <span class="n">-UseSsl</span> +<span class="p">}</span> <span class="k">Else</span> <span class="p">{</span> + <span class="nb">Write-Host</span> <span class="s2">&quot;Up and running&quot;</span> +<span class="p">}</span> +</code></pre></div>Microsoft Against Covid2020-10-03T19:00:00-03:002020-10-03T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-03:/en/microsoft-against-covid.html<p>Has your job been affected by covid? Well, last week I've posted on <a href="https://grepora.com/2020/09/17/microsoft-ignite-certification-voucher/">Grepora</a> about a Free Certification Voucher that Microsoft was giving away at the Microsoft Ignite event. After that, I found that they were also giving a huge discount to people who have had their job affected by …</p><p>Has your job been affected by covid? Well, last week I've posted on <a href="https://grepora.com/2020/09/17/microsoft-ignite-certification-voucher/">Grepora</a> about a Free Certification Voucher that Microsoft was giving away at the Microsoft Ignite event. After that, I found that they were also giving a huge discount to people who have had their job affected by covid pandemic. </p> +<p>To see more details about if you were eligible, access <a href="https://docs.microsoft.com/en-us/learn/certifications/skillingoffer">https://docs.microsoft.com/en-us/learn/certifications/skillingoffer</a>.</p>The power of PowerShell2020-09-21T19:00:00-03:002020-09-21T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-09-21:/en/the-power-of-powershell.html<p>As a long time Linux user, I've automated a few things with bash scripts and stayed away from PowerShell... I've moved to a Windows environment a few years ago and still, haven gave a shot to PS. But why not? I've made a few scripts to automate some tasks at …</p><p>As a long time Linux user, I've automated a few things with bash scripts and stayed away from PowerShell... I've moved to a Windows environment a few years ago and still, haven gave a shot to PS. But why not? I've made a few scripts to automate some tasks at a Protheus server.</p> +<p>I found the PS scripts being easy to read and understand. Bellow, we have a script to remove files filtering their extension (or no extension at all like the following script). </p> +<div class="highlight"><pre><span></span><code><span class="nb">Get-ChildItem</span> <span class="s2">&quot;C:\TOTVS\protheus_data\system&quot;</span> <span class="o">-File</span> <span class="n">-Filter</span> <span class="p">*.</span> <span class="p">|</span> <span class="nb">Move-Item</span> <span class="n">-Force</span> <span class="n">-Destination</span> <span class="p">{</span> + <span class="cm">&lt;# Diretory where the files will be moved. You can use Date formats to help name it #&gt;</span> + <span class="cm">&lt;# LastWriteTime proprtie from the current file #&gt;</span> + <span class="nv">$dir</span> <span class="p">=</span> <span class="s2">&quot;C:\bad_files\{0:yyyy\\MM\\dd}&quot;</span> <span class="o">-f</span> <span class="nv">$_</span><span class="p">.</span><span class="n">LastWriteTime</span> + <span class="nv">$null</span> <span class="p">=</span> <span class="n">mkdir</span> <span class="nv">$dir</span> <span class="n">-Force</span> + <span class="s2">&quot;$dir\</span><span class="p">$(</span><span class="nv">$_</span><span class="p">.</span><span class="n">Name</span><span class="p">)</span><span class="s2">&quot;</span> +<span class="p">}</span> +</code></pre></div> + +<p>Have you ever been in the need to remove files based on other file content? Bello a script where I read a file that has the names of files that I want to remove. </p> +<div class="highlight"><pre><span></span><code><span class="k">foreach</span><span class="p">(</span><span class="nv">$line</span> <span class="k">in</span> <span class="nb">Get-Content</span> <span class="p">.\</span><span class="n">Desktop</span><span class="p">\</span><span class="n">bad_files</span><span class="p">.</span><span class="n">txt</span><span class="p">)</span> <span class="p">{</span> + <span class="k">if</span> <span class="p">(</span><span class="nb">Test-Path</span><span class="p">(</span><span class="s1">&#39;\\x.y.z.a\c$\TOTVS\protheus_data\xmls\&#39;</span><span class="p">+</span><span class="nv">$line</span><span class="p">+</span><span class="s1">&#39;.xml&#39;</span><span class="p">))</span> <span class="p">{</span> + <span class="nb">Remove-Item</span><span class="p">(</span><span class="s1">&#39;\\x.y.z.a\c$\TOTVS\protheus_data\xmls\&#39;</span><span class="p">+</span><span class="nv">$line</span><span class="p">+</span><span class="s1">&#39;.xml&#39;</span><span class="p">)</span> + <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> + <span class="nb">echo </span><span class="nv">$line</span> <span class="p">+</span> <span class="s1">&#39; - File not found&#39;</span> + <span class="p">}</span> +<span class="p">}</span> +</code></pre></div> + +<p>And a bonus script to stop/start services (if you handle some Protheus Server, you know why I do that).</p> +<div class="highlight"><pre><span></span><code><span class="nv">$servicesNames</span> <span class="p">=</span> <span class="s1">&#39;app_main&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker1&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker2&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker3&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker4&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker5&#39;</span> + +<span class="nb">Write-host</span> <span class="s2">&quot;Stoping Services&quot;</span> +<span class="nb">Write-host</span> <span class="s2">&quot;--------------------------&quot;</span> + +<span class="k">foreach</span> <span class="p">(</span><span class="nv">$srv</span> <span class="k">in</span> <span class="nv">$servicesNames</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Write-host</span> <span class="s2">&quot;Stopping: &quot;</span> <span class="p">+</span> <span class="nv">$srv</span> + <span class="nv">$SrvPID</span> <span class="p">=</span> <span class="p">(</span><span class="nb">get-wmiobject</span> <span class="n">win32_service</span> <span class="p">|</span> <span class="nb">where </span><span class="p">{</span> <span class="nv">$_</span><span class="p">.</span><span class="n">name</span> <span class="o">-eq</span> <span class="nv">$srv</span><span class="p">}).</span><span class="n">processID</span> + <span class="nb">Write-host</span> <span class="s2">&quot;PID: &quot;</span> <span class="p">+</span> <span class="nv">$SrvPID</span> + + <span class="cm">&lt;# Force if the proccess is stucked #&gt;</span> + <span class="nb">Stop-Process</span> <span class="nv">$SrvPID</span> <span class="n">-Force</span> + <span class="nb">Write-host</span> <span class="s2">&quot;PDI &quot;</span> <span class="p">+</span> <span class="nv">$SrvPID</span> <span class="p">+</span> <span class="s2">&quot; stopped&quot;</span> +<span class="p">}</span> + + +<span class="nb">Write-host</span> <span class="s2">&quot;Starting Services&quot;</span> +<span class="nb">Write-host</span> <span class="s2">&quot;--------------------------&quot;</span> + +<span class="k">foreach</span> <span class="p">(</span><span class="nv">$srv</span> <span class="k">in</span> <span class="nv">$servicesNames</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Write-host</span> <span class="s2">&quot;Starting: &quot;</span> <span class="p">+</span> <span class="nv">$srv</span> + <span class="nb">Start-Service</span> <span class="nv">$srv</span> +<span class="p">}</span> +</code></pre></div> + +<p>Do you have any automated script? Share with us :)</p>Top Level Statement in C# 92020-07-29T19:00:00-03:002020-07-29T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-07-29:/en/top_level_statement_csharp_9.html<p>Hey folks, I'm coming along to tell you a few things about the new feature of C# 9. Every time you want to start a new project, you always have the same Main File, with the same structure. At the next version of C# (version 9), we'll have a new …</p><p>Hey folks, I'm coming along to tell you a few things about the new feature of C# 9. Every time you want to start a new project, you always have the same Main File, with the same structure. At the next version of C# (version 9), we'll have a new feature called <code>Top Level Statement</code>. With that, we'll be able to code our app without any namespace/class/public void static main structure. Take a look at the code below.</p> +<div class="highlight"><pre><span></span><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span> + +<span class="n">Console</span><span class="p">.</span><span class="n">WriteLine</span><span class="p">(</span><span class="s">&quot;Hello World!&quot;</span><span class="p">);</span> +</code></pre></div> + +<p>It looks pretty simple, but with this, you can play around with your code, and even code a simple/tiny Web API. To start playing with the new features, firstly download the <a href="https://dotnet.microsoft.com/download/dotnet/5.0">.net 5 SDK</a> and change your <code>.csproj</code> file to target the .net 5 and language preview like bellow.</p> +<div class="highlight"><pre><span></span><code><span class="nt">&lt;Project</span> <span class="na">Sdk=</span><span class="s">&quot;Microsoft.NET.Sdk&quot;</span><span class="nt">&gt;</span> + <span class="nt">&lt;PropertyGroup&gt;</span> + <span class="nt">&lt;OutputType&gt;</span>Exe<span class="nt">&lt;/OutputType&gt;</span> + <span class="nt">&lt;TargetFramework&gt;</span>net5.0<span class="nt">&lt;/TargetFramework&gt;</span> + <span class="nt">&lt;LangVersion&gt;</span>preview<span class="nt">&lt;/LangVersion&gt;</span> + <span class="nt">&lt;/PropertyGroup&gt;</span> +<span class="nt">&lt;/Project&gt;</span> +</code></pre></div> + +<p>And you're ready to play with the awesome features available in the preview. Let's code a way to get the image of the day from NASA API and print the Picture of the Day. No awesome code here, it's really a way to show how simple a simple call could be. After here, why not save the image in a file? Maybe send the file over telegram?</p> +<div class="highlight"><pre><span></span><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Net.Http</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Text.Json</span><span class="p">;</span> + +<span class="kt">var</span> <span class="n">API</span> <span class="p">=</span> <span class="s">&quot;https://api.nasa.gov/planetary/apod?hd=true&amp;api_key=DEMO_KEY&quot;</span><span class="p">;</span> +<span class="kt">var</span> <span class="n">cli</span> <span class="p">=</span> <span class="k">new</span> <span class="n">HttpClient</span><span class="p">();</span> + +<span class="kt">var</span> <span class="n">response</span> <span class="p">=</span> <span class="k">await</span> <span class="n">cli</span><span class="p">.</span><span class="n">GetAsync</span><span class="p">(</span><span class="n">API</span><span class="p">);</span> +<span class="kt">var</span> <span class="n">data</span> <span class="p">=</span> <span class="n">JsonSerializer</span><span class="p">.</span><span class="n">Deserialize</span><span class="p">&lt;</span><span class="n">NasaApi</span><span class="p">&gt;(</span><span class="k">await</span> <span class="n">response</span><span class="p">.</span><span class="n">Content</span><span class="p">.</span><span class="n">ReadAsStringAsync</span><span class="p">());</span> + +<span class="n">Console</span><span class="p">.</span><span class="n">WriteLine</span><span class="p">(</span><span class="n">data</span><span class="p">.</span><span class="n">Url</span><span class="p">);</span> +</code></pre></div> + +<p>That's it for today folks. Keep an eye open for the awesome features C# 9 will bring to us, there's plenty more features already available.</p>Zabbix poller processes more than 75%2020-07-02T19:00:00-03:002020-07-02T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-07-02:/en/zabbix-poller-processes-more-than-75.html<p>Hey folks, this is the third post about tweaking the Zabbix configurations. All changes that I've suggested here were based on a Zabbix Server with 50+ hosts. Another thing that can happen to your server, it's the poller get overwhelmed by the amount of servers that need to be polled …</p><p>Hey folks, this is the third post about tweaking the Zabbix configurations. All changes that I've suggested here were based on a Zabbix Server with 50+ hosts. Another thing that can happen to your server, it's the poller get overwhelmed by the amount of servers that need to be polled plus the ones that are not responding. Bellow two images where you can see the log and the graphic where you can see the usage percent. </p> +<p><img alt="Dashboard log about the poller processes" src="/images/zabbix_pooler.png"></p> +<p><img alt="Graph showing the utilization percent of each collector" src="/images/zabbix_pooler_3.png"></p> +<p>To solve, let's go back to the <code>zabbix_server.conf</code> file and find two variables, <code>StartPollers</code> and <code>StartPollersUnreachable</code>. Increase them as needed. There's no magic number, you must see what works for you. But keep in mind that the <code>StartPollersUnreachable</code> is responsible for that host that can't be "reached" (of course) and will hold your poller more time.</p> +<div class="highlight"><pre><span></span><code><span class="c1">### Option: StartPollers</span> +<span class="c1"># Number of pre-forked instances of pollers.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 0-1000</span> +<span class="c1"># Default:</span> +<span class="na">StartPollers</span><span class="o">=</span><span class="s">20</span> + +<span class="c1">#...</span> + +<span class="c1">### Option: StartPollersUnreachable</span> +<span class="c1"># Number of pre-forked instances of pollers for unreachable hosts (including IPMI and Java).</span> +<span class="c1"># At least one poller for unreachable hosts must be running if regular, IPMI or Java pollers</span> +<span class="c1"># are started.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 0-1000</span> +<span class="c1"># Default:</span> +<span class="na">StartPollersUnreachable</span><span class="o">=</span><span class="s">5</span> +</code></pre></div> + +<p>After the change, restart the server and wait a few moments and take a look again at your dashboard. Bellow the effect that I've got.</p> +<p><img alt="Graph showing the new utilization percent of the processes after the changes" src="/images/zabbix_pooler_4.png"></p>Monitoring a Website heath with Azure Functions2020-06-22T19:00:00-03:002020-06-22T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-06-22:/en/monitoring-website-heath-with-azure-functions.html<p>Sometimes you get your self in need to monitor a website's health or it's content for changes. Of course, there's plenty of options out there, but for the sake of curiosity, let's code our own to see what we can do. First things first. Everything you'll see here, you can …</p><p>Sometimes you get your self in need to monitor a website's health or it's content for changes. Of course, there's plenty of options out there, but for the sake of curiosity, let's code our own to see what we can do. First things first. Everything you'll see here, you can achieve with the <a href="https://azure.microsoft.com/free/">free tier</a> of azure.</p> +<p>The main idea of our app will be to monitor website health (status code). To create a new Azure Function Project, follow the steps below.</p> +<p><img alt="Steps to create a azure function project" src="/images/azure_functions.gif"></p> +<p>After creating the project, you'll have a few files. Open your main file and start coding. The main file will have a function called <code>Run</code> and you can code your request method. I've created an <code>async</code> method to make the request and log the output at the console. The full code you can see below.</p> +<div class="highlight"><pre><span></span><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Linq</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Net.Http</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Threading.Tasks</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">Microsoft.Azure.WebJobs</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">Microsoft.Azure.WebJobs.Host</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">Microsoft.Extensions.Logging</span><span class="p">;</span> + +<span class="k">namespace</span> <span class="nn">Sipmann.CheckMySite</span> +<span class="p">{</span> + <span class="k">public</span> <span class="k">static</span> <span class="k">class</span> <span class="nc">HttpCheck</span> + <span class="p">{</span> + + <span class="k">private</span> <span class="k">static</span> <span class="k">async</span> <span class="n">Task</span> <span class="nf">GetTask</span><span class="p">(</span><span class="kt">string</span> <span class="n">url</span><span class="p">,</span> <span class="n">ILogger</span> <span class="n">log</span><span class="p">)</span> + <span class="p">{</span> + <span class="kt">var</span> <span class="n">request</span> <span class="p">=</span> <span class="k">new</span> <span class="n">HttpRequestMessage</span><span class="p">(</span><span class="n">HttpMethod</span><span class="p">.</span><span class="n">Get</span><span class="p">,</span> <span class="n">url</span><span class="p">);</span> + + <span class="kt">var</span> <span class="n">client</span> <span class="p">=</span> <span class="k">new</span> <span class="n">HttpClient</span><span class="p">();</span> + <span class="kt">var</span> <span class="n">response</span> <span class="p">=</span> <span class="k">await</span> <span class="n">client</span><span class="p">.</span><span class="n">SendAsync</span><span class="p">(</span><span class="n">request</span><span class="p">);</span> + + <span class="k">if</span> <span class="p">(</span><span class="n">response</span><span class="p">.</span><span class="n">IsSuccessStatusCode</span><span class="p">)</span> + <span class="p">{</span> + <span class="n">log</span><span class="p">.</span><span class="n">LogInformation</span><span class="p">(</span><span class="err">$</span><span class="s">&quot;URL ${url} esta OK&quot;</span><span class="p">);</span> + <span class="p">}</span> + <span class="k">else</span> + <span class="p">{</span> + <span class="n">log</span><span class="p">.</span><span class="n">LogInformation</span><span class="p">(</span><span class="err">$</span><span class="s">&quot;URL ${url} não esta OK&quot;</span><span class="p">);</span> + <span class="p">}</span> + <span class="p">}</span> + +<span class="na"> [FunctionName(&quot;HttpCheck&quot;)]</span> + <span class="k">public</span> <span class="k">static</span> <span class="k">void</span> <span class="nf">Run</span><span class="p">([</span><span class="n">TimerTrigger</span><span class="p">(</span><span class="s">&quot;0 */5 * * * *&quot;</span><span class="p">)]</span><span class="n">TimerInfo</span> <span class="n">myTimer</span><span class="p">,</span> <span class="n">ILogger</span> <span class="n">log</span><span class="p">)</span> + <span class="p">{</span> + <span class="kt">var</span> <span class="n">urls</span> <span class="p">=</span> <span class="k">new</span><span class="p">[]{</span><span class="s">&quot;https://www.sipmann.com&quot;</span><span class="p">,</span> <span class="s">&quot;https://www.canezecanez.com.br&quot;</span><span class="p">};</span> + + <span class="c1">// Start every request and wait for them all to complete</span> + <span class="n">Task</span><span class="p">.</span><span class="n">WaitAll</span><span class="p">(</span><span class="n">urls</span><span class="p">.</span><span class="n">Select</span><span class="p">(</span><span class="n">url</span> <span class="p">=&gt;</span> <span class="n">GetTask</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">log</span><span class="p">)).</span><span class="n">ToArray</span><span class="p">());</span> + <span class="n">log</span><span class="p">.</span><span class="n">LogInformation</span><span class="p">(</span><span class="err">$</span><span class="s">&quot;Finalizou a fila&quot;</span><span class="p">);</span> + <span class="p">}</span> + <span class="p">}</span> +<span class="p">}</span> +</code></pre></div> + +<p>Now you can enhance the function and maybe send some alerts like a Telegram message when one of your sites went down.</p>Azure Data Fundamentals certification with 80% discount2020-06-09T12:30:00-03:002020-06-09T12:30:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-06-09:/en/azure-data-fundamentals-certification-80-discount.html<p>Hey folks, if you want to achieve some certification this year, keep an eye open for vouchers. A few months ago, Oracle released a set of free courses with certifications. Now it's Microsoft time. Microsoft is updating they're certifications and we have a voucher of 80% discount using the coupon …</p><p>Hey folks, if you want to achieve some certification this year, keep an eye open for vouchers. A few months ago, Oracle released a set of free courses with certifications. Now it's Microsoft time. Microsoft is updating they're certifications and we have a voucher of 80% discount using the coupon <strong>DP900Norfolk</strong> at the checkout of the beta certification DP-900. </p> +<p>Be aware that this certification is in beta and the result won't be instantly available as the regular ones. Access the following link and schedule your exam. <a href="https://docs.microsoft.com/pt-br/learn/certifications/exams/dp-900" target="_blank">https://docs.microsoft.com/pt-br/learn/certifications/exams/dp-900</a>.</p> +<p><strong>Update:</strong> There is a 80% voucher also for <a href="https://docs.microsoft.com/en-us/learn/certifications/azure-ai-fundamentals" target="_blank">https://docs.microsoft.com/en-us/learn/certifications/azure-ai-fundamentals</a>. Voucher: <strong>AI900Saratoga</strong></p>Zabbix ICMP pinger processes more than 75%2020-05-25T16:00:00-03:002020-05-25T16:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-05-25:/en/zabbix-icmp-pinger-processes-more-than-75.html<p>So your monitoring sytems have grown and your zabbix started loggin "Zabbix icmp pinger processes more than 75% busy" at the dashboard.</p> +<p><img alt="Dashboard do zabbix avisando sobre o erro" src="/images/zabbix_pinger01.png"></p> +<p>All you have to do is open your config file (<code>/etc/zabbix/zabbix_server.conf</code>) and find the a tag named <code>StartPingers</code>. It'll be commented by default. Uncomment it …</p><p>So your monitoring sytems have grown and your zabbix started loggin "Zabbix icmp pinger processes more than 75% busy" at the dashboard.</p> +<p><img alt="Dashboard do zabbix avisando sobre o erro" src="/images/zabbix_pinger01.png"></p> +<p>All you have to do is open your config file (<code>/etc/zabbix/zabbix_server.conf</code>) and find the a tag named <code>StartPingers</code>. It'll be commented by default. Uncomment it and set it's value to something like 3 or 4. It should solve your problem.</p> +<div class="highlight"><pre><span></span><code><span class="c1">### Option: StartPingers</span> +<span class="c1"># Number of pre-forked instances of ICMP pingers.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 0-1000</span> +<span class="c1"># Default:</span> +<span class="nv">StartPingers</span><span class="o">=</span><span class="m">4</span> +</code></pre></div> + +<h2>How many Pingers do I need?</h2> +<p>Well, there is no exact answer to this. If you set it too high, you'll be wasting resources. The best way to solve, it's increasing them as soon as you notice the percentage growing.</p>Zabbix Server Out of Memory2020-02-27T19:00:00-03:002020-02-27T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-02-27:/en/zabbix-server-out-of-memory-crash.html<p>Do you have a crashing Zabbix Server and looking through the log <code>/var/log/zabbix/zabbix_server.log</code> you see the following out of memory message?</p> +<div class="highlight"><pre><span></span><code>__mem_malloc: skipped <span class="m">0</span> asked <span class="m">24</span> skip_min <span class="m">18446744073709551615</span> skip_max <span class="m">0</span> +<span class="o">[</span>file:dbconfig.c,line:94<span class="o">]</span> __zbx_mem_realloc<span class="o">()</span>: out of memory <span class="o">(</span>requested <span class="m">16</span> bytes<span class="o">)</span> +<span class="o">[</span>file:dbconfig.c,line …</code></pre></div><p>Do you have a crashing Zabbix Server and looking through the log <code>/var/log/zabbix/zabbix_server.log</code> you see the following out of memory message?</p> +<div class="highlight"><pre><span></span><code>__mem_malloc: skipped <span class="m">0</span> asked <span class="m">24</span> skip_min <span class="m">18446744073709551615</span> skip_max <span class="m">0</span> +<span class="o">[</span>file:dbconfig.c,line:94<span class="o">]</span> __zbx_mem_realloc<span class="o">()</span>: out of memory <span class="o">(</span>requested <span class="m">16</span> bytes<span class="o">)</span> +<span class="o">[</span>file:dbconfig.c,line:94<span class="o">]</span> __zbx_mem_realloc<span class="o">()</span>: please increase CacheSize configuration parameter +</code></pre></div> + +<p>Besides the clear solution to the error, that's a common issue on servers that have a few monitoring items on it (servers, switches, firewalls, databases, etc...). To solve, go to your zabbix_server.conf and look for the CacheSize property and set it to a higher value. Its default should be 8M. At a customer that has somewhere between 4 servers, 7 firewalls/appliances, and a few other things, a 32M did the job, but you can set up to 8G.</p> +<p>See ya folks.</p>Flutter + firebase auth crashing2019-10-03T19:00:00-03:002019-10-03T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2019-10-03:/en/flutter_with_firebase_auth_crashing.html<p>Hey Folks, recently I've started learning <a href="https://flutter.dev/">Flutter</a> and right after a TODO List, I tried a Firebase integration. But as soon as I started setting the dependencies, my app stopped opening... just a crash. After a few logs digging, I've found the following log.</p> +<div class="highlight"><pre><span></span><code>AndroidRuntime: FATAL EXCEPTION: main +AndroidRuntime: Process …</code></pre></div><p>Hey Folks, recently I've started learning <a href="https://flutter.dev/">Flutter</a> and right after a TODO List, I tried a Firebase integration. But as soon as I started setting the dependencies, my app stopped opening... just a crash. After a few logs digging, I've found the following log.</p> +<div class="highlight"><pre><span></span><code>AndroidRuntime: FATAL EXCEPTION: main +AndroidRuntime: Process: com.example.diadocasal, PID: <span class="m">13672</span> +AndroidRuntime: java.lang.NoClassDefFoundError: Failed resolution of: Landroid/support/v4/util/ArrayMap<span class="p">;</span> +AndroidRuntime: at com.google.android.gms.internal.measurement.zzca.&lt;clinit&gt;<span class="o">(</span>Unknown Source:60<span class="o">)</span> +AndroidRuntime: at com.google.android.gms.internal.measurement.zzcm.zzr<span class="o">(</span>Unknown Source:7<span class="o">)</span> +AndroidRuntime: at com.google.android.gms.measurement.internal.zzfj.&lt;init&gt;<span class="o">(</span>Unknown Source:23<span class="o">)</span> +</code></pre></div> + +<p>Notice the "NoClassDefFound" of an ArrayMap. To solve that I did the following changes to the files:</p> +<div class="highlight"><pre><span></span><code><span class="c1">//build.gradle file</span> + <span class="n">ext</span><span class="p">.</span><span class="na">kotlin_version</span> <span class="o">=</span> <span class="err">&#39;</span><span class="mf">1.3.20</span><span class="err">&#39;</span> +<span class="o">[</span><span class="p">...</span><span class="o">]</span> + <span class="n">dependencies</span> <span class="p">{</span> + <span class="n">classpath</span> <span class="err">&#39;</span><span class="n">com</span><span class="p">.</span><span class="na">android</span><span class="p">.</span><span class="na">tools</span><span class="p">.</span><span class="na">build</span><span class="p">:</span><span class="n">gradle</span><span class="p">:</span><span class="mf">3.3.0</span><span class="err">&#39;</span> <span class="c1">// gradle version</span> +</code></pre></div> + +<div class="highlight"><pre><span></span><code><span class="c1">;gradle.properties file</span> +<span class="na">org.gradle.jvmargs</span><span class="o">=</span><span class="s">-Xmx1536M ;mine have just this line at first</span> +<span class="na">android.useAndroidX</span><span class="o">=</span><span class="s">true ; uses androidX instead of the default support library</span> +<span class="na">android.enableJetifier</span><span class="o">=</span><span class="s">true ; uses jetpack libraries</span> +<span class="na">android.enableR8</span><span class="o">=</span><span class="s">true ; the new code shriker</span> +</code></pre></div> + +<p>After that, voilà, app up and running.</p>Removing a user from SQL Server database who owns a schema2019-09-06T07:00:00-03:002020-10-21T18:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2019-09-06:/en/removing-user-from-sql-server-database.html<p>Your customer urge you to drop a user from the MsSQL Server database, but you stuck with the following related error:</p> +<div class="highlight"><pre><span></span><code><span class="n">Error</span><span class="o">:</span> <span class="mi">15138</span> <span class="n">The</span> <span class="n">database</span> <span class="n">principal</span> <span class="n">owns</span> <span class="n">a</span> <span class="n">schema</span> <span class="k">in</span> <span class="n">the</span> <span class="n">database</span><span class="o">,</span> <span class="n">and</span> <span class="n">cannot</span> <span class="n">be</span> <span class="n">dropped</span><span class="o">.</span> +</code></pre></div> + +<p>That means that the user owns one or more shcemas of your database. If …</p><p>Your customer urge you to drop a user from the MsSQL Server database, but you stuck with the following related error:</p> +<div class="highlight"><pre><span></span><code><span class="n">Error</span><span class="o">:</span> <span class="mi">15138</span> <span class="n">The</span> <span class="n">database</span> <span class="n">principal</span> <span class="n">owns</span> <span class="n">a</span> <span class="n">schema</span> <span class="k">in</span> <span class="n">the</span> <span class="n">database</span><span class="o">,</span> <span class="n">and</span> <span class="n">cannot</span> <span class="n">be</span> <span class="n">dropped</span><span class="o">.</span> +</code></pre></div> + +<p>That means that the user owns one or more shcemas of your database. If you don't have access to the SSMS to see which schema or objects the user owns, the following SQL should do the job.</p> +<div class="highlight"><pre><span></span><code><span class="k">USE</span><span class="w"> </span><span class="o">[</span><span class="n">DATABASENAME</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> + +<span class="k">select</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Objeto</span><span class="p">,</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Owner</span><span class="w"></span> +<span class="k">from</span><span class="w"> </span><span class="n">sys</span><span class="p">.</span><span class="n">schemas</span><span class="w"> </span><span class="n">so</span><span class="w"></span> +<span class="k">inner</span><span class="w"> </span><span class="k">join</span><span class="w"> </span><span class="n">sysusers</span><span class="w"> </span><span class="n">su</span><span class="w"> </span><span class="k">on</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">principal_id</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">uid</span><span class="w"></span> +<span class="k">where</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">&#39;username&#39;</span><span class="w"></span> + +<span class="k">select</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Objeto</span><span class="p">,</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Owner</span><span class="p">,</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">xtype</span><span class="w"> </span><span class="n">Tipo</span><span class="w"></span> +<span class="k">from</span><span class="w"> </span><span class="n">sys</span><span class="p">.</span><span class="n">sysobjects</span><span class="w"> </span><span class="n">so</span><span class="w"></span> +<span class="k">inner</span><span class="w"> </span><span class="k">join</span><span class="w"> </span><span class="n">sysusers</span><span class="w"> </span><span class="n">su</span><span class="w"> </span><span class="k">on</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">uid</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">uid</span><span class="w"></span> +<span class="k">where</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">&#39;username&#39;</span><span class="w"></span> +</code></pre></div> + +<p>Once you have the objects/schemas owned by the user, you can change them with the following SQL (schema change sample):</p> +<div class="highlight"><pre><span></span><code><span class="k">USE</span><span class="w"> </span><span class="o">[</span><span class="n">DATABASENAME</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +<span class="k">ALTER</span><span class="w"> </span><span class="k">AUTHORIZATION</span><span class="w"> </span><span class="k">ON</span><span class="w"> </span><span class="k">SCHEMA</span><span class="o">::[</span><span class="n">db_datareader</span><span class="o">]</span><span class="w"> </span><span class="k">TO</span><span class="w"> </span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="w"> </span><span class="c1">-- new owner username</span> +<span class="k">ALTER</span><span class="w"> </span><span class="k">AUTHORIZATION</span><span class="w"> </span><span class="k">ON</span><span class="w"> </span><span class="k">SCHEMA</span><span class="o">::[</span><span class="n">db_datawriter</span><span class="o">]</span><span class="w"> </span><span class="k">TO</span><span class="w"> </span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +</code></pre></div> + +<p>Then you're ready to drop the user <code>DROP USER [username]</code></p> +<h2>How to list all the schemas and it's owners?</h2> +<p>Here's a script to list schemas and it's owners.</p> +<div class="highlight"><pre><span></span><code><span class="k">USE</span><span class="w"> </span><span class="o">[</span><span class="n">DATABASENAME</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +<span class="k">SELECT</span><span class="w"></span> +<span class="w"> </span><span class="nf">schema_name</span><span class="p">(</span><span class="nf">schema_id</span><span class="p">)</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="n">schemaname</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="nf">user_name</span><span class="p">(</span><span class="n">schm</span><span class="p">.</span><span class="n">principal_id</span><span class="p">)</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="n">username</span><span class="p">,</span><span class="w"> </span><span class="o">*</span><span class="w"></span> +<span class="k">FROM</span><span class="w"> </span><span class="n">sys</span><span class="p">.</span><span class="n">schemas</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="n">schm</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +</code></pre></div>Limiting Connection Resources on SQL Server2019-08-12T12:00:00-03:002019-08-12T12:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2019-08-12:/en/limiting-connection-resources-sql-server.html<p>Have you ever suffered from a slow SQLServer database? Someone love to run that heavy query in the database? Resource Governor to the rescue. You can set a few rules on how users (connections actually) will use the server/database resources based on a few things.</p> +<p>First things first, if …</p><p>Have you ever suffered from a slow SQLServer database? Someone love to run that heavy query in the database? Resource Governor to the rescue. You can set a few rules on how users (connections actually) will use the server/database resources based on a few things.</p> +<p>First things first, if you don't have DAC enabled, enable it now. Dealing with resource governor can lock you out of the database and leave you without action (almost... you can start the server with -c -m -f).</p> +<p>Now to understand how Resource Governor works, we have a few keywords <code>resource pool</code>, <code>workload group</code> e <code>Classifier Function</code>.</p> +<p><img alt="Pool Sample" src="/images/sql-pool.png"></p> +<h2>Resource Pool</h2> +<p>First, we have the Resource Pool, with is the bigger resource group that we have the ability to manage. With it, we can set a few things like: <code>MIN_CPU_PERCENT</code>, <code>MAX_CPU_PERCENT</code>, <code>MIN_MEMORY_PERCENT</code>, <code>MAX_MEMORY_PERCENT</code>, <code>MIN_IOPS_PER_VOLUME</code>, and <code>MAX_IOPS_PER_VOLUME</code>.</p> +<p>Be aware that the <code>MAX_CPU_PERCENT</code> will just "works" when there is another connection with a higher priority, otherwise it will use what is available. Let's create a pool.</p> +<div class="highlight"><pre><span></span><code><span class="k">CREATE</span><span class="w"> </span><span class="n">RESOURCE</span><span class="w"> </span><span class="n">POOL</span><span class="w"> </span><span class="o">[</span><span class="n">SpreadSheet</span><span class="o">]</span><span class="w"></span> +<span class="k">WITH</span><span class="w"> </span><span class="p">(</span><span class="w"></span> +<span class="w"> </span><span class="n">MIN_CPU_PERCENT</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">MAX_CPU_PERCENT</span><span class="o">=</span><span class="mi">20</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">MIN_MEMORY_PERCENT</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">MAX_MEMORY_PERCENT</span><span class="o">=</span><span class="mi">20</span><span class="w"></span> +<span class="p">);</span><span class="w"></span> +</code></pre></div> + +<p>## Workload Group</p> +<p>Then we have a workload group that "works" inside a pool, so you can have another granularity on how you can split your resources. Again, we have a few options: <code>IMPORTANCE</code>, <code>REQUEST_MAX_CPU_TIME_SEC</code>, <code>REQUEST_MAX_MEMORY_GRANT_PERCENT</code>, <code>GROUP_MAX_REQUESTS</code>.</p> +<p>The <code>IMPORTANCE</code> set guesses what... the importance of that workload inside the pool, you can set LOW, MEDIUM, HIGH. GROUP_MAX_REQUESTS sets how many requests can run at the same time inside that workload (0 will set as NO LIMIT)</p> +<div class="highlight"><pre><span></span><code><span class="k">CREATE</span><span class="w"> </span><span class="n">WORKLOAD</span><span class="w"> </span><span class="k">GROUP</span><span class="w"> </span><span class="o">[</span><span class="n">DepartmentA</span><span class="o">]</span><span class="w"> </span> +<span class="k">WITH</span><span class="w"> </span><span class="p">(</span><span class="w"></span> +<span class="w"> </span><span class="n">GROUP_MAX_REQUESTS</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">IMPORTANCE</span><span class="o">=</span><span class="n">LOW</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">REQUEST_MAX_CPU_TIME_SEC</span><span class="o">=</span><span class="mi">10</span><span class="p">,</span><span class="w"> </span><span class="c1">-- Time running/using CPU</span> +<span class="w"> </span><span class="n">REQUEST_MAX_MEMORY_GRANT_PERCENT</span><span class="o">=</span><span class="mi">15</span><span class="w"></span> +<span class="p">)</span><span class="w"> </span><span class="k">USING</span><span class="w"> </span><span class="o">[</span><span class="n">SpreadSheet</span><span class="o">]</span><span class="p">;</span><span class="w"> </span><span class="c1">-- pool name here</span> +</code></pre></div> + +<h2>Classifier Function</h2> +<p>This is where everything begins... This is the entry point where you should set the group name. It's a function that will run for every new connection so be aware that if your function runs lots of queries or some heavy stuff... that time will be added to the connection handshake. If the function returns NULL or a group name that doesn't exist, the 'default' group will be used... Yes, there is a default workload group where everything runs where there's no classifier.</p> +<div class="highlight"><pre><span></span><code><span class="k">CREATE</span><span class="w"> </span><span class="k">FUNCTION</span><span class="w"> </span><span class="n">fnClassWorkloadGovernor</span><span class="p">()</span><span class="w"> </span> +<span class="k">RETURNS</span><span class="w"> </span><span class="n">SYSNAME</span><span class="w"> </span><span class="k">WITH</span><span class="w"> </span><span class="n">SCHEMABINDING</span><span class="w"> </span> +<span class="k">AS</span><span class="w"> </span> +<span class="k">BEGIN</span><span class="w"> </span> +<span class="w"> </span><span class="k">IF</span><span class="w"> </span><span class="nf">APP_NAME</span><span class="p">()</span><span class="w"> </span><span class="ow">LIKE</span><span class="w"> </span><span class="s1">&#39;%Excel%&#39;</span><span class="w"></span> +<span class="w"> </span><span class="k">RETURN</span><span class="w"> </span><span class="s1">&#39;DepartmentA&#39;</span><span class="w"></span> + +<span class="w"> </span><span class="k">IF</span><span class="w"> </span><span class="nf">HOST_NAME</span><span class="p">()</span><span class="w"> </span><span class="ow">LIKE</span><span class="w"> </span><span class="s1">&#39;%THAT_MACHINE_OR_APP_SERVER%&#39;</span><span class="w"></span> +<span class="w"> </span><span class="k">RETURN</span><span class="w"> </span><span class="s1">&#39;LowPriority&#39;</span><span class="w"></span> + +<span class="w"> </span><span class="k">RETURN</span><span class="w"> </span><span class="k">NULL</span><span class="w"></span> +<span class="k">END</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> + +<span class="k">ALTER</span><span class="w"> </span><span class="n">RESOURCE</span><span class="w"> </span><span class="n">GOVERNOR</span><span class="w"> </span><span class="k">WITH</span><span class="w"> </span><span class="p">(</span><span class="n">CLASSIFIER_FUNCTION</span><span class="o">=</span><span class="n">dbo</span><span class="p">.</span><span class="n">fnClassWorkloadGovernor</span><span class="p">);</span><span class="w"></span> +<span class="k">ALTER</span><span class="w"> </span><span class="n">RESOURCE</span><span class="w"> </span><span class="n">GOVERNOR</span><span class="w"> </span><span class="k">RECONFIGURE</span><span class="p">;</span><span class="w"></span> +</code></pre></div> + +<p>There you go... now you have a fully working resource governor, but look out that If you want to delete that classifier function, first you have to remove it from the resource governor (look the SCHEMABINDING at the create up there).</p> +<p>To disable Resource Governor</p> +<div class="highlight"><pre><span></span><code><span class="k">ALTER</span><span class="w"> </span><span class="n">RESOURCE</span><span class="w"> </span><span class="n">GOVERNOR</span><span class="w"> </span><span class="k">WITH</span><span class="w"> </span><span class="p">(</span><span class="n">CLASSIFIER_FUNCTION</span><span class="o">=</span><span class="k">null</span><span class="p">)</span><span class="w"></span> +<span class="k">ALTER</span><span class="w"> </span><span class="n">RESOURCE</span><span class="w"> </span><span class="n">GOVERNOR</span><span class="w"> </span><span class="k">RECONFIGURE</span><span class="w"></span> + +<span class="k">ALTER</span><span class="w"> </span><span class="n">RESOURCE</span><span class="w"> </span><span class="n">GOVERNOR</span><span class="w"> </span><span class="n">DISABLE</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +</code></pre></div>Using git hooks to easy your life2019-07-30T20:00:00-03:002019-07-30T20:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2019-07-30:/en/using_git_hooks_easy_your_life.html<p>Hey folks, it's been a time since my last post. In the meantime, I moved to another state, changed job, and started learning new kinds of stuff. Today I would like to share one thing that I usually do with my small git projects. Git has many cool features, git …</p><p>Hey folks, it's been a time since my last post. In the meantime, I moved to another state, changed job, and started learning new kinds of stuff. Today I would like to share one thing that I usually do with my small git projects. Git has many cool features, git hooks were one of them. I'll talk about the pre-commit hook today.</p> +<p>Let's say that, for some reason, you don't have a CI tool/server running after every commit and you want to enforce that every developer runs the tests before every commit? Git pre-commit to the rescue. You can code the hooks with shell, ruby, python, and I could be wrong, but even PHP would work. pre-commit is a client-side hook (we have server side too) and he's located inside the <cite>.git/hooks</cite> folder. Let's jump to the code... Create a file called 'pre-commit' inside that folder with the following code.</p> +<div class="highlight"><pre><span></span><span class="ch">#!/bin/bash</span> +npm <span class="nb">test</span> <span class="c1"># assuming you&#39;re using it inside a nodeJS project</span> +</pre></div> +<p>Don't forget to make the script executable!! Now break your test and try to commit. That's easy but can save you from breaking the tests at the main CI/Travis/Codeship/etc and being notified by email :). Why not even validate the lint of your project or check if the coverage doesn't fall? Does your team/company have a patter for commit messages? No problem, there is a hook called <cite>commit-msg</cite> that you can use to validate your message.</p> +Microservices with NodeJS, Express.js and RabbitMQ Part 22018-04-13T13:00:00-03:002018-04-13T13:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-04-13:/en/microservices_nodejs_express_rabbitmq_part_2.html<p>If you haven't read the <a class="reference external" href="https://www.sipmann.com/microservices_nodejs_express_rabbitmq_part_1-en.html">part 1</a> go ahead and read it... It can be useful :). Or if for some reason you want to start now, you can grab the project where we stopped <a class="reference external" href="https://github.com/sipmann/imagecompacter/releases/tag/v1">here</a> and get along. On this part, we'll implement the RabbitMQ queue and see how we …</p><p>If you haven't read the <a class="reference external" href="https://www.sipmann.com/microservices_nodejs_express_rabbitmq_part_1-en.html">part 1</a> go ahead and read it... It can be useful :). Or if for some reason you want to start now, you can grab the project where we stopped <a class="reference external" href="https://github.com/sipmann/imagecompacter/releases/tag/v1">here</a> and get along. On this part, we'll implement the RabbitMQ queue and see how we can get the best of our app and server with that.</p> +<p>Before we began coding, let's understand why we are going to use RabbitMQ if what we have now works? If you check again, you'll see how long it takes to answer the request with the optimized image. It takes a few seconds, so imagine an online service with thousands of request to optimize images (like <a class="reference external" href="https://tinypng.com/">TinyPNG</a>) how long is it gonna take to answer every request? How much of your server is it gonna take? With only one service running, probably the server will crash.</p> +<p>With a queue, we can schedule the requests so we can use the amount of memory and processor that our server has, without taking more than we can. It's better to take a few seconds to answer the request then throw some error to the user. Want more? With RabbitMQ we can see how the queue is doing and we can add more consumers (workers) to it and get things done quicker and distribute the job.</p> +<p>First of all, we need an up and running Rabbit server, for the sake of simplicity, I'll use a Docker container with it inside.</p> +<div class="highlight"><pre><span></span>docker run -d --name rabbit -p <span class="m">5672</span>:5672 -p <span class="m">8080</span>:15672 rabbitmq:3-management +</pre></div> +<p>You can see that we're running the rabbitmq:3-management image, which provides us a web interface to see how things are going. After that, if you look at our code you'll see that all the job is made at the '/upload' route, and that's what we'll change.</p> +<p>First, we need to understand what we need from RabbitMQ. We need something that, we send an image to a queue and get an optimized image back from that. There is a name for that, is RPC (remote procedure call) and there are two ways of doing this with rabbit. Both the ways you can see on their tutorial page. We'll use the approach that uses a global channel whose id is randomly generated (you'll use the name 'amq.rabbitmq.reply-to' but the rabbit will do the job).</p> +<p>Let's start importing the library, defining a few variables and defining a init function that will establish a connection with the rabbit server and create our RPC queue. The RPC queue it's where we'll receive the answer from the consumer (our worker).</p> +<div class="highlight"><pre><span></span><span class="c1">//import the library</span> +<span class="kr">const</span> <span class="nx">amqplib</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;amqplib&#39;</span><span class="p">);</span> + +<span class="c1">//queue channel</span> +<span class="kd">let</span> <span class="nx">channel</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span> +<span class="c1">//queue name</span> +<span class="kr">const</span> <span class="nx">QUEUE</span> <span class="o">=</span> <span class="s1">&#39;optimizeimg&#39;</span><span class="p">;</span> + +<span class="c1">//...</span> + +<span class="kd">function</span> <span class="nx">init</span><span class="p">()</span> <span class="p">{</span> + <span class="k">return</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;amqplib&#39;</span><span class="p">).</span><span class="nx">connect</span><span class="p">(</span><span class="s1">&#39;amqp://localhost&#39;</span><span class="p">)</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">conn</span> <span class="p">=&gt;</span> <span class="nx">conn</span><span class="p">.</span><span class="nx">createChannel</span><span class="p">())</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">ch</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="nx">channel</span> <span class="o">=</span> <span class="nx">ch</span><span class="p">;</span> + + <span class="c1">//this queue is a &quot;Direct reply-to&quot; read more at the docs</span> + <span class="c1">//When some msg comes in, we &quot;emit&quot; a message to the proper &quot;correlationId&quot; listener</span> + <span class="nx">ch</span><span class="p">.</span><span class="nx">consume</span><span class="p">(</span><span class="s1">&#39;amq.rabbitmq.reply-to&#39;</span><span class="p">,</span> <span class="nx">msg</span> <span class="p">=&gt;</span> <span class="nx">eventEmitter</span><span class="p">.</span><span class="nx">emit</span><span class="p">(</span><span class="nx">msg</span><span class="p">.</span><span class="nx">properties</span><span class="p">.</span><span class="nx">correlationId</span><span class="p">,</span> <span class="nx">msg</span><span class="p">.</span><span class="nx">content</span><span class="p">),</span> <span class="p">{</span><span class="nx">noAck</span><span class="o">:</span> <span class="kc">true</span><span class="p">});</span> + <span class="p">});</span> +<span class="p">}</span> + +<span class="c1">//Random id generator</span> +<span class="kd">function</span> <span class="nx">randomid</span><span class="p">()</span> <span class="p">{</span> + <span class="k">return</span> <span class="k">new</span> <span class="nb">Date</span><span class="p">().</span><span class="nx">getTime</span><span class="p">().</span><span class="nx">toString</span><span class="p">()</span> <span class="o">+</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">random</span><span class="p">().</span><span class="nx">toString</span><span class="p">()</span> <span class="o">+</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">random</span><span class="p">().</span><span class="nx">toString</span><span class="p">();</span> +<span class="p">}</span> + +<span class="nx">app</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="s1">&#39;/upload&#39;</span><span class="p">,</span> <span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="kd">let</span> <span class="nx">img</span> <span class="o">=</span> <span class="nx">req</span><span class="p">.</span><span class="nx">files</span><span class="p">.</span><span class="nx">image</span><span class="p">;</span> + + <span class="kd">let</span> <span class="nx">id</span> <span class="o">=</span> <span class="nx">randomid</span><span class="p">();</span> + + <span class="c1">//Event listener that will fire when the proper randomid is provided</span> + <span class="nx">eventEmitter</span><span class="p">.</span><span class="nx">once</span><span class="p">(</span><span class="nx">id</span><span class="p">,</span> <span class="nx">msg</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="nx">res</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="nx">msg</span><span class="p">,</span> <span class="s1">&#39;binary&#39;</span><span class="p">);</span> + <span class="nx">res</span><span class="p">.</span><span class="nx">end</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="s1">&#39;binary&#39;</span><span class="p">);</span> + <span class="p">});</span> + + <span class="c1">//Checks if the queue exists, and create it if needed.</span> + <span class="nx">channel</span><span class="p">.</span><span class="nx">assertQueue</span><span class="p">(</span><span class="nx">QUEUE</span><span class="p">)</span> + <span class="c1">//Sent the buffered img to the queue with the ID and the responseQueue</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="nx">channel</span><span class="p">.</span><span class="nx">sendToQueue</span><span class="p">(</span><span class="nx">QUEUE</span><span class="p">,</span> <span class="nx">img</span><span class="p">.</span><span class="nx">data</span><span class="p">,</span> <span class="p">{</span><span class="nx">correlationId</span><span class="o">:</span><span class="nx">id</span><span class="p">,</span> <span class="nx">replyTo</span><span class="o">:</span> <span class="s1">&#39;amq.rabbitmq.reply-to&#39;</span><span class="p">}));</span> + +<span class="p">});</span> + +<span class="c1">//Finally start the app with the given port number</span> +<span class="c1">//now we initialize the rabbitmq connection before start the server</span> +<span class="nx">init</span><span class="p">()</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="nx">app</span><span class="p">.</span><span class="nx">listen</span><span class="p">(</span><span class="mi">4000</span><span class="p">,</span> <span class="p">()</span> <span class="p">=&gt;</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;Example app listening on port 4000!&#39;</span><span class="p">)))</span> + <span class="p">.</span><span class="k">catch</span><span class="p">(</span><span class="nx">err</span><span class="p">=&gt;</span><span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="nx">err</span><span class="p">));</span> +</pre></div> +<p>Ok, now we have our server code rewritten so let's see our worker code. Create a file named 'worker.js' and let's see how it's gonna be. It's really simple. You initialize a connection with RabbitMQ too, create a channel, check if the queue exists and start watching for incoming messages. When an image arrives, we do the job with it and send back to the &quot;replyTo&quot; queue the optimized image for the proper sender (correlationId). In the end, we do an acknowledge of the message so it get's out from the queue.</p> +<div class="highlight"><pre><span></span><span class="kr">const</span> <span class="nx">imagemin</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;imagemin&#39;</span><span class="p">);</span> +<span class="kr">const</span> <span class="nx">imageminPngquant</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;imagemin-pngquant&#39;</span><span class="p">);</span> + +<span class="kd">let</span> <span class="nx">channel</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span> +<span class="kr">const</span> <span class="nx">QUEUE</span> <span class="o">=</span> <span class="s1">&#39;imgqueue&#39;</span><span class="p">;</span> + +<span class="nx">require</span><span class="p">(</span><span class="s1">&#39;amqplib&#39;</span><span class="p">).</span><span class="nx">connect</span><span class="p">(</span><span class="s1">&#39;amqp://localhost&#39;</span><span class="p">)</span> +<span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">conn</span> <span class="p">=&gt;</span><span class="nx">conn</span><span class="p">.</span><span class="nx">createChannel</span><span class="p">())</span> +<span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">ch</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="nx">ch</span><span class="p">.</span><span class="nx">assertQueue</span><span class="p">(</span><span class="nx">QUEUE</span><span class="p">)</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="c1">//Watch incomming messages</span> + <span class="nx">ch</span><span class="p">.</span><span class="nx">consume</span><span class="p">(</span><span class="nx">QUEUE</span><span class="p">,</span> <span class="nx">msg</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="nx">imagemin</span><span class="p">.</span><span class="nx">buffer</span><span class="p">(</span><span class="nx">msg</span><span class="p">.</span><span class="nx">content</span><span class="p">,</span> <span class="p">{</span> + <span class="nx">plugins</span><span class="o">:</span> <span class="p">[</span><span class="nx">imageminPngquant</span><span class="p">()]</span> + <span class="p">})</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">out</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="c1">//Send back to the sender (replyTo) queue and give the correlationId back</span> + <span class="c1">//so we can emit the event.</span> + <span class="nx">ch</span><span class="p">.</span><span class="nx">sendToQueue</span><span class="p">(</span><span class="nx">msg</span><span class="p">.</span><span class="nx">properties</span><span class="p">.</span><span class="nx">replyTo</span><span class="p">,</span> <span class="nx">out</span><span class="p">,</span> <span class="p">{</span> + <span class="nx">correlationId</span><span class="o">:</span> <span class="nx">msg</span><span class="p">.</span><span class="nx">properties</span><span class="p">.</span><span class="nx">correlationId</span> + <span class="p">});</span> + + <span class="c1">//Acknowledge the job done with the message.</span> + <span class="nx">ch</span><span class="p">.</span><span class="nx">ack</span><span class="p">(</span><span class="nx">msg</span><span class="p">);</span> + <span class="p">});</span> + <span class="p">});</span> + <span class="p">});</span> +<span class="p">});</span> +</pre></div> +<p>The key points here are. Open just one connection to the hole server. You CAN create one channel for every request that you receive, but it can take some time if you have a really big cluster of RabbitMQ. It was a quick tutorial, but I hope that it was able to clear a few questions that you might have when working with rabbit and express.</p> +Microservices with NodeJS, Express.js and RabbitMQ Part 12018-04-04T11:25:00-03:002018-04-04T11:25:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-04-04:/en/microservices_nodejs_express_rabbitmq_part_1.html<p>This is the first part of a microservices development series. The service will consist of the bellow architecture, where we will expose an image optimizer service that will forward the request to a <a class="reference external" href="https://www.rabbitmq.com/">RabbitMQ</a> queue and answer with the bytecode of the optimized image. It shouldn't be a long series …</p><p>This is the first part of a microservices development series. The service will consist of the bellow architecture, where we will expose an image optimizer service that will forward the request to a <a class="reference external" href="https://www.rabbitmq.com/">RabbitMQ</a> queue and answer with the bytecode of the optimized image. It shouldn't be a long series so let's see what we can do.</p> +<img alt="Service architecture" src="/images/microservices_rabit_pt1.png" /> +<p>Let's get our environment working. First, we'll need to install the libraries that we'll use.</p> +<p>Create a dir and initialize the nodejs application inside it (<cite>npm init</cite>) and then let's install the deps.</p> +<ul class="simple"> +<li>amqplib - AMQP lib to interact with rabbitmq</li> +<li>express - Do our basic rest API</li> +<li>express-fileupload - easy file upload parser</li> +<li>imagemin and imagemin-pngquant - our image compacter</li> +</ul> +<div class="highlight"><pre><span></span>npm install --save express amqplib express-fileupload imagemin imagemin-pngquant +</pre></div> +<p>Now let's write the entry points for our service, we'll have two basic entry points. The path <cite>/</cite> that will have a welcome message, the second path will be <cite>/upload</cite> and this is the one that will handle the image and produce a job for our workers.</p> +<div class="highlight"><pre><span></span><span class="kr">const</span> <span class="nx">express</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;express&#39;</span><span class="p">);</span> +<span class="kr">const</span> <span class="nx">fileUpload</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;express-fileupload&#39;</span><span class="p">);</span> + +<span class="c1">//Instantiate the app and set the fileupload parser to manage files</span> +<span class="kr">const</span> <span class="nx">app</span> <span class="o">=</span> <span class="nx">express</span><span class="p">();</span> +<span class="nx">app</span><span class="p">.</span><span class="nx">use</span><span class="p">(</span><span class="nx">fileUpload</span><span class="p">());</span> + +<span class="c1">//Our index entry point</span> +<span class="nx">app</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;/&#39;</span><span class="p">,</span> <span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="nx">res</span><span class="p">.</span><span class="nx">send</span><span class="p">(</span><span class="s1">&#39;Hello From ImageCompacter service&#39;</span><span class="p">));</span> + +<span class="c1">//The path that will handle the image file and throw them to the queue</span> +<span class="nx">app</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="s1">&#39;/upload&#39;</span><span class="p">,</span> <span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="c1">//With express-fileupload we can grab the files like this</span> + <span class="kd">let</span> <span class="nx">img</span> <span class="o">=</span> <span class="nx">req</span><span class="p">.</span><span class="nx">files</span><span class="p">.</span><span class="nx">image</span><span class="p">;</span> <span class="c1">//&quot;image&quot; is the name of the input</span> + + <span class="nx">res</span><span class="p">.</span><span class="nx">send</span><span class="p">(</span><span class="s1">&#39;Not ready yet&#39;</span><span class="p">);</span> +<span class="p">});</span> + +<span class="c1">//Finally start the app with the given port number</span> +<span class="nx">app</span><span class="p">.</span><span class="nx">listen</span><span class="p">(</span><span class="mi">4000</span><span class="p">,</span> <span class="p">()</span> <span class="p">=&gt;</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;Example app listening on port 4000!&#39;</span><span class="p">));</span> +</pre></div> +<p>Let's check if it works, run the service with node.</p> +<div class="highlight"><pre><span></span>node index.js +Example app listening on port <span class="m">4000</span>! +</pre></div> +<p>Open the browser and check if it prints our hello message when accessing <cite>localhost:4000</cite>. Works? Greate. Now let's work with the image and see how we do it. To optimize our image, we'll use the library imagemin and <a class="reference external" href="https://www.npmjs.com/package/imagemin-pngquant">imagemin-pngquant</a>, it will be that simple for now, we'll work with rabbitmq latter.</p> +<div class="highlight"><pre><span></span><span class="kr">const</span> <span class="nx">imagemin</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;imagemin&#39;</span><span class="p">);</span> +<span class="kr">const</span> <span class="nx">imageminPngquant</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;imagemin-pngquant&#39;</span><span class="p">);</span> +<span class="c1">//...</span> + +<span class="c1">//The path that will handle the image file and throw them to the queue</span> +<span class="nx">app</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="s1">&#39;/upload&#39;</span><span class="p">,</span> <span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="kd">let</span> <span class="nx">img</span> <span class="o">=</span> <span class="nx">req</span><span class="p">.</span><span class="nx">files</span><span class="p">.</span><span class="nx">image</span><span class="p">;</span> <span class="c1">//&quot;image&quot; is the name of the input</span> + + <span class="nx">imagemin</span><span class="p">.</span><span class="nx">buffer</span><span class="p">(</span><span class="nx">img</span><span class="p">.</span><span class="nx">data</span><span class="p">,</span> <span class="p">{</span> + <span class="nx">plugins</span><span class="o">:</span> <span class="p">[</span><span class="nx">imageminPngquant</span><span class="p">()]</span> + <span class="p">})</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">out</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="nx">res</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="nx">out</span><span class="p">,</span><span class="s1">&#39;binary&#39;</span><span class="p">);</span> + <span class="nx">res</span><span class="p">.</span><span class="nx">end</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="s1">&#39;binary&#39;</span><span class="p">);</span> + <span class="p">});</span> +<span class="p">});</span> + + <span class="c1">//...</span> +</pre></div> +<p>Use <a class="reference external" href="https://www.getpostman.com/">Postman</a> to test the request. To see if it will work, make a request to <cite>http://localhost:4000/upload</cite> with a formdata with a file. Select the &quot;send and Download&quot; instead of &quot;Send&quot; and you should have an image after that. Bellow an image of how your postman should be.</p> +<img alt="Postman" src="/images/microservice_postman.png" /> +<p>That's it for today, next week we'll change our code to use RabbitMQ.</p> +Connecting to a database through SSH2018-03-29T10:03:00-03:002018-03-29T10:03:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-03-29:/en/connecting_to_database_through_ssh.html<p>If someday, for some reason, you need to establish a connection with a database which is behind a firewall and you only have SSH access on that server (and you don't want to use a CLI) you can do an SSH tunnel. It's pretty simple, bellow has a sample of …</p><p>If someday, for some reason, you need to establish a connection with a database which is behind a firewall and you only have SSH access on that server (and you don't want to use a CLI) you can do an SSH tunnel. It's pretty simple, bellow has a sample of how to allow connections to a remote Firebird database.</p> +<div class="highlight"><pre><span></span>ssh -L <span class="m">3051</span>:192.168.1.9:3050 username@192.168.1.9 +</pre></div> +<p>The <cite>-L</cite> parameter tells to SSH do a local port forwarding on local port <cite>3051</cite> to remote port <cite>3050</cite>. You can use it to a connection with many services, not just databases.</p> +<p>You can do the reverse kind of tunnel, forward connections from the host to your local machine, you just have to change the parameter form &quot;-L&quot; to &quot;-R&quot; and the port order is inverted, first come the port where the server will listen and after your localhost port. This remote port forwarding must be enabled on the server. Look for <cite>GatewayPorts</cite> at the ssh config file.</p> +<div class="highlight"><pre><span></span>ssh -R <span class="m">3050</span>:localhost:3050 username@192.168.1.9 +</pre></div> +<p>Why whould you need something like that?? Let's say you want to share a localhost site/database with a friend, but your internet connection don't allow you to expose any port but you have access to a remote server witch can do that. Problem solved ;).</p> +Now posting on Grepora2018-03-24T00:40:00-03:002018-03-24T00:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-03-24:/en/now_posting_on_grepora.html<p>A few weeks ago I started posting at <a class="reference external" href="https://grepora.com/blog/">Grepora</a> blog. If you like or are looking for some Oracle related stuff, Grepora it's a good place to go and spend a time reading :). From time to time I'll be posting there, it doesn't mean that this blog will be closed …</p><p>A few weeks ago I started posting at <a class="reference external" href="https://grepora.com/blog/">Grepora</a> blog. If you like or are looking for some Oracle related stuff, Grepora it's a good place to go and spend a time reading :). From time to time I'll be posting there, it doesn't mean that this blog will be closed or anything like that, but probably this one will be more focused on Front-end stuff, a few tricks with linux and a lil less with Java.</p> +Scaffolding a React app with Parcel and Yeoman2018-03-17T13:00:00-03:002018-03-17T13:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-03-17:/en/scaffolding_react_app_with_parcel_yeoman.html<p>Since <a class="reference external" href="https://parceljs.org/">Parcel JS</a> arrived, I've been using it a lot as an awesome alternative for WebPack. Webpack isn't bad but IMO it's too complex for the job and parcel do the same (at least the basic) with almost zero configuration. But if you need to create many apps (like a …</p><p>Since <a class="reference external" href="https://parceljs.org/">Parcel JS</a> arrived, I've been using it a lot as an awesome alternative for WebPack. Webpack isn't bad but IMO it's too complex for the job and parcel do the same (at least the basic) with almost zero configuration. But if you need to create many apps (like a react app) over and over again, it get's a lil boring following the basic steps.</p> +<div class="highlight"><pre><span></span>npm init -y +npm install --save react +npm install --save react-dom +npm install --save-dev parcel-bundler +npm install --save-dev babel-preset-env +npm install --save-dev babel-preset-react + +<span class="c1">#create .babelrc file</span> +<span class="c1">#create html, css, jsx files</span> + +parcel index.html +</pre></div> +<p>It's not a hard job, a simple shell script do the job, but what if you need some IFs when creating the app, or even change a few things at the <cite>package.json</cite>? A shell script still does the job, but come on... There is a better way. <a class="reference external" href="http://yeoman.io/">Yeoman</a> is here for you. I've already <a class="reference external" href="https://www.sipmann.com/en/desenvolvendo-app-firefoxos-pt.html">talked about it</a> on another post (Portuguese post).</p> +<p>Straight to the point, I've released a Yeoman generator to get the things a lil quicker. The name is <a class="reference external" href="https://www.npmjs.com/package/generator-parcel-react">generator-parcel-react</a> and it still lacks a few things that I will deal with soon. It's pretty simple to use it.</p> +<div class="highlight"><pre><span></span><span class="c1">#First time only</span> +npm install -g yo +npm install -g generator-parcel-react + +<span class="c1">#every time you create a new app</span> +yo parcel-react +</pre></div> +<p>And that's it. Right now you can scaffold and app with React, SASS and React Router. Hope you like it and feel free to ask new features.</p> +Could not open connection with MySQL and Hibernate2018-03-09T12:35:00-03:002018-03-09T12:35:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-03-09:/en/cloud-not-open-connection-java-mysql-hibernate.html<p>Last day I decided to deploy a MySQL Docker image to work with my Java application. I've been using PostgreSQL instead and have no problems at all, but after I moved to MySQL, the app didn't connect anymore with the database and throw some &quot;Could not open connection&quot; at my …</p><p>Last day I decided to deploy a MySQL Docker image to work with my Java application. I've been using PostgreSQL instead and have no problems at all, but after I moved to MySQL, the app didn't connect anymore with the database and throw some &quot;Could not open connection&quot; at my face, but why? I've tried to connect to it manually and got the same problem.</p> +<p>After some research, I found that the true error should be java.sql.SQLException: null, message from server: &quot;Host '172.17.0.4' is not allowed to connect to this MySQL server&quot; but it wasn't showing to me...</p> +<p>After all, be aware that with the docker image MySQL:5.7.21 (latest version right now) the root user isn't allowed to remote connect to the database (it's alright, security reasons) and if you still want to do remote connections to it with root there are a few things you can do.</p> +<ol class="arabic simple"> +<li>Create a user or allow root to access from other IPs.</li> +</ol> +<div class="highlight"><pre><span></span><span class="o">#</span><span class="k">No</span> <span class="k">access</span> <span class="k">to</span> <span class="k">user</span> <span class="n">root</span> <span class="k">on</span> <span class="k">any</span> <span class="n">other</span> <span class="n">IP</span> +<span class="k">SELECT</span> <span class="k">User</span><span class="p">,</span> <span class="k">Host</span> <span class="k">FROM</span> <span class="n">mysql</span><span class="p">.</span><span class="k">user</span><span class="p">;</span> +<span class="o">+</span><span class="c1">---------------+-----------+</span> +<span class="o">|</span> <span class="k">User</span> <span class="o">|</span> <span class="k">Host</span> <span class="o">|</span> +<span class="o">+</span><span class="c1">---------------+-----------+</span> +<span class="o">|</span> <span class="n">healthchecker</span> <span class="o">|</span> <span class="n">localhost</span> <span class="o">|</span> +<span class="o">|</span> <span class="n">root</span> <span class="o">|</span> <span class="n">localhost</span> <span class="o">|</span> +<span class="o">+</span><span class="c1">---------------+-----------+</span> +<span class="mi">2</span> <span class="k">rows</span> <span class="k">in</span> <span class="k">set</span> <span class="p">(</span><span class="mi">0</span><span class="p">.</span><span class="mi">01</span> <span class="n">sec</span><span class="p">)</span> + +<span class="k">CREATE</span> <span class="k">USER</span> <span class="s1">&#39;newuser&#39;</span><span class="o">@</span><span class="s1">&#39;%&#39;</span> <span class="n">IDENTIFIED</span> <span class="k">BY</span> <span class="s1">&#39;password&#39;</span><span class="p">;</span> <span class="o">#%</span> <span class="n">mean</span> <span class="k">any</span> <span class="n">IP</span> +<span class="k">GRANT</span> <span class="k">ALL</span> <span class="k">PRIVILEGES</span> <span class="k">ON</span> <span class="o">*</span><span class="p">.</span><span class="o">*</span> <span class="k">TO</span> <span class="s1">&#39;newuser&#39;</span><span class="o">@</span><span class="s1">&#39;%&#39;</span><span class="p">;</span> <span class="o">#*</span><span class="p">.</span><span class="o">*</span> <span class="n">mean</span> <span class="k">database</span><span class="p">.</span><span class="k">table</span> <span class="p">;)</span> +</pre></div> +<ol class="arabic simple" start="2"> +<li>Use MariaDB instead, witch come (at least on the version 10.2.13) with root allowed to do remote connections and will work like MySQL :)</li> +</ol> +<p>I changed to <a class="reference external" href="https://mariadb.org/">MariaDB</a> as it work without creating user or any changes on the Java code or the <cite>docker run command</cite>.</p> +Solving java.net.SocketException: Protocol family unavailable on a Java + Docker + WildFly2018-03-04T17:40:00-03:002018-03-04T17:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-03-04:/en/socketException-protocol-family-unavailable-java-docker-wildfly.html<p>On the last days I've been playing with <a class="reference external" href="http://wildfly-swarm.io/">WildFly Swarm</a> and I decided to deploy a simple app with Docker. Should work fine, at least that was what I thought. Built a container with the following Dockerfile and instead of a working web app, all that I got was the …</p><p>On the last days I've been playing with <a class="reference external" href="http://wildfly-swarm.io/">WildFly Swarm</a> and I decided to deploy a simple app with Docker. Should work fine, at least that was what I thought. Built a container with the following Dockerfile and instead of a working web app, all that I got was the error <cite>java.net.SocketException: Protocol family unavailable</cite>.</p> +<div class="highlight"><pre><span></span><span class="k">FROM</span> <span class="s">java:openjdk-8-jdk</span> + +<span class="k">COPY</span> target/issues.jar /opt/issues.jar + +<span class="k">EXPOSE</span><span class="s"> 8080</span> + +<span class="k">CMD</span> <span class="p">[</span><span class="s2">&quot;java&quot;</span><span class="p">,</span><span class="s2">&quot;-jar&quot;</span><span class="p">,</span><span class="s2">&quot;/opt/issues.jar&quot;</span><span class="p">]</span> +</pre></div> +<p>For some reason, WildFly and Java decided to use the IPv6 network interface from Docker instead the v4, so all you have to do is tell Java to prefer IPv4 instead with the following configuration option in your pom.xml file inside your WildFly plugin.</p> +<div class="highlight"><pre><span></span><span class="nt">&lt;plugin&gt;</span> + <span class="nt">&lt;groupId&gt;</span>org.wildfly.swarm<span class="nt">&lt;/groupId&gt;</span> + <span class="nt">&lt;artifactId&gt;</span>wildfly-swarm-plugin<span class="nt">&lt;/artifactId&gt;</span> + <span class="nt">&lt;version&gt;</span>2018.2.0<span class="nt">&lt;/version&gt;</span> + + <span class="c">&lt;!-- ADD THIS --&gt;</span> + <span class="nt">&lt;configuration&gt;</span> + <span class="nt">&lt;mainClass&gt;</span>org.wildfly.swarm.examples.netflix.ribbon.frontend.Main<span class="nt">&lt;/mainClass&gt;</span> + <span class="nt">&lt;properties&gt;</span> + <span class="nt">&lt;java.net.preferIPv4Stack&gt;</span>true<span class="nt">&lt;/java.net.preferIPv4Stack&gt;</span> + <span class="nt">&lt;/properties&gt;</span> + <span class="nt">&lt;/configuration&gt;</span> +</pre></div> +<p>Another way to solve is adding the same properties to the run command at the Dockerfile, so you choose where you'll add it. Bellow the Dockerfile solution.</p> +<div class="highlight"><pre><span></span><span class="k">FROM</span> <span class="s">java:openjdk-8-jdk</span> +<span class="k">ENV</span> <span class="nv">JAVA_OPTS</span><span class="o">=</span><span class="s2">&quot;-Djava.net.preferIPv4Stack=true -Djava.net.preferIPv4Addresses=true&quot;</span> + +<span class="k">COPY</span> target/issues.jar /opt/issues.jar + +<span class="k">EXPOSE</span><span class="s"> 8080</span> + +<span class="k">ENTRYPOINT</span> <span class="nb">exec</span> java <span class="nv">$JAVA_OPTS</span> -jar /opt/issues.jar +</pre></div> +Change display settings on linux with Disper2018-02-27T12:40:00-03:002018-02-27T12:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-02-27:/en/linux-external-display-with-disper.html<p>From time to time, I change the Linux distro on my laptop or just do a fresh install on it. And once in a while, have random problems with external displays. It can be something really &quot;simple&quot; like don't detecting the external monitor or something crazy like the image below …</p><p>From time to time, I change the Linux distro on my laptop or just do a fresh install on it. And once in a while, have random problems with external displays. It can be something really &quot;simple&quot; like don't detecting the external monitor or something crazy like the image below.</p> +<img alt="Display bug" src="/images/bug.png" /> +<p>As you can see at the image, the mint detected the display but mirrored it in a crazy way that works but doesn't at the same time. If you try anything and doesn't get working, or just wanna skip the whole job of configuring complexes text files, give a try to <a class="reference external" href="http://willem.engen.nl/projects/disper/">Disper</a>. Download the latest version. +Extract it on any folder, and make install it (on the extracted folder).</p> +<div class="highlight"><pre><span></span>make install +</pre></div> +<p>After that, you can start using it... There are a few options that will serve you well.</p> +<div class="highlight"><pre><span></span>disper -e <span class="c1">#extend your display</span> +</pre></div> +<div class="highlight"><pre><span></span>disper -c <span class="c1">#clone your display</span> +</pre></div> +<div class="highlight"><pre><span></span>disper -s <span class="c1">#only your external display</span> +</pre></div> +Java - Files.readAllBytes throws OutOfMemory2018-02-17T13:00:00-02:002018-02-17T13:00:00-02:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-02-17:/en/reading-files-java-readAllBytes-outofmemory.html<p>When you need to interact with files, there's the possibility to read all bytes from the file with <cite>Files.readAllBytes</cite>. But be aware of the kinds of files your application will deal with because the Java API files have a limit for the buffer that is defined as <cite>Integer.MAX_VALUE …</cite></p><p>When you need to interact with files, there's the possibility to read all bytes from the file with <cite>Files.readAllBytes</cite>. But be aware of the kinds of files your application will deal with because the Java API files have a limit for the buffer that is defined as <cite>Integer.MAX_VALUE</cite> as you can see above or at the OpenJDK sources.</p> +<div class="highlight"><pre><span></span><span class="kd">public</span> <span class="kd">static</span> <span class="kt">byte</span><span class="o">[]</span> <span class="nf">readAllBytes</span><span class="p">(</span><span class="n">Path</span> <span class="n">path</span><span class="p">)</span> <span class="kd">throws</span> <span class="n">IOException</span> <span class="p">{</span> + <span class="k">try</span> <span class="p">(</span><span class="n">FileChannel</span> <span class="n">fc</span> <span class="o">=</span> <span class="n">FileChannel</span><span class="p">.</span><span class="na">open</span><span class="p">(</span><span class="n">path</span><span class="p">))</span> <span class="p">{</span> + <span class="kt">long</span> <span class="n">size</span> <span class="o">=</span> <span class="n">fc</span><span class="p">.</span><span class="na">size</span><span class="p">();</span> + <span class="k">if</span> <span class="p">(</span><span class="n">size</span> <span class="o">&gt;</span> <span class="p">(</span><span class="kt">long</span><span class="p">)</span><span class="n">Integer</span><span class="p">.</span><span class="na">MAX_VALUE</span><span class="p">)</span> + <span class="k">throw</span> <span class="k">new</span> <span class="n">OutOfMemoryError</span><span class="p">(</span><span class="s">&quot;Required array size too large&quot;</span><span class="p">);</span> + + <span class="kt">byte</span><span class="o">[]</span> <span class="n">arr</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">byte</span><span class="o">[</span><span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">size</span><span class="o">]</span><span class="p">;</span> + <span class="n">ByteBuffer</span> <span class="n">bb</span> <span class="o">=</span> <span class="n">ByteBuffer</span><span class="p">.</span><span class="na">wrap</span><span class="p">(</span><span class="n">arr</span><span class="p">);</span> + <span class="k">while</span> <span class="p">(</span><span class="n">bb</span><span class="p">.</span><span class="na">hasRemaining</span><span class="p">())</span> <span class="p">{</span> + <span class="k">if</span> <span class="p">(</span><span class="n">fc</span><span class="p">.</span><span class="na">read</span><span class="p">(</span><span class="n">bb</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> + <span class="c1">// truncated</span> + <span class="k">break</span><span class="p">;</span> + <span class="p">}</span> + <span class="p">}</span> + + <span class="kt">int</span> <span class="n">nread</span> <span class="o">=</span> <span class="n">bb</span><span class="p">.</span><span class="na">position</span><span class="p">();</span> + <span class="k">return</span> <span class="p">(</span><span class="n">nread</span> <span class="o">==</span> <span class="n">size</span><span class="p">)</span> <span class="o">?</span> <span class="n">arr</span> <span class="p">:</span> <span class="n">Arrays</span><span class="p">.</span><span class="na">copyOf</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="n">nread</span><span class="p">);</span> + <span class="p">}</span> +<span class="p">}</span> +</pre></div> +<p>With that in mind, check if isn't better read chunks of bytes e work with that slice in exchange of loading the whole file into the memory ;). Above a simple example of how you can read chunks of bytes from the file.</p> +<div class="highlight"><pre><span></span><span class="kt">byte</span><span class="o">[]</span> <span class="n">buffer</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">byte</span><span class="o">[</span><span class="mi">1024</span><span class="o">]</span><span class="p">;</span> +<span class="n">FileInputStream</span> <span class="n">in</span> <span class="o">=</span> <span class="k">new</span> <span class="n">FileInputStream</span><span class="p">(</span><span class="n">file</span><span class="p">);</span> +<span class="kt">int</span> <span class="n">rc</span> <span class="o">=</span> <span class="n">in</span><span class="p">.</span><span class="na">read</span><span class="p">(</span><span class="n">buffer</span><span class="p">);</span> +<span class="k">while</span> <span class="p">(</span><span class="n">rc</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span> +<span class="p">{</span> + <span class="c1">//crazy stuff here with buffer</span> + <span class="n">rc</span> <span class="o">=</span> <span class="n">in</span><span class="p">.</span><span class="na">read</span><span class="p">(</span><span class="n">buffer</span><span class="p">);</span> +<span class="p">}</span> +</pre></div> + \ No newline at end of file diff --git a/en/feeds/mauricio-camargo-sipmann.atom.xml.gz b/en/feeds/mauricio-camargo-sipmann.atom.xml.gz new file mode 100644 index 000000000..300a85b12 Binary files /dev/null and b/en/feeds/mauricio-camargo-sipmann.atom.xml.gz differ diff --git a/en/feeds/mauricio-camargo-sipmann.rss.xml b/en/feeds/mauricio-camargo-sipmann.rss.xml new file mode 100644 index 000000000..0f0f534e7 --- /dev/null +++ b/en/feeds/mauricio-camargo-sipmann.rss.xml @@ -0,0 +1,28 @@ + +Sipmann - Maurício Camargo Sipmannhttps://www.sipmann.com/en/Mon, 21 Dec 2020 13:30:00 -0300Monitoring MySQL restarts with PowerShellhttps://www.sipmann.com/en/monitoring-mysql-restarts-with-powershell.html<p>Hey folks, it's time for another PowerShell script. If you haven't seen the other ones, check the links below.</p> +<ul> +<li><a href="https://www.sipmann.com/en/monitoring-mysql-replication-with-powershell.html">Monitoring MySQL replication with PowerShell</a></li> +</ul> +<p>Well, this one it's a pretty simple script, but again, if your customer doesn't have a Zabbix server or doesn't allow you to setup one to …</p>Maurício Camargo SipmannMon, 21 Dec 2020 13:30:00 -0300tag:www.sipmann.com,2020-12-21:/en/monitoring-mysql-restarts-with-powershell.htmlPowerShellMySQLMySQL RestartPowershell monitoringChanging a MySQL user password across multiple application instances without downtimehttps://www.sipmann.com/en/mysql-dual-password-functionality.html<p>Do you need to change the password of a MySQL user that it's being used in an application, and can't allow a single downtime? Well, MySQL 8.0.14 came with a feature called <a href="https://dev.mysql.com/doc/refman/8.0/en/password-management.html#dual-passwords">Dual Password Support</a>, with it you can change the password keeping the previous password as a …</p>Maurício Camargo SipmannWed, 09 Dec 2020 13:40:00 -0300tag:www.sipmann.com,2020-12-09:/en/mysql-dual-password-functionality.htmlMySQLMySQLMySQL Dual PasswordApache Nifi JSON to SQL Replacing underscorehttps://www.sipmann.com/en/apache-nifi-json-to-sql-replacing-underscore.html<p>Recently I was doing some ETL with Apache NiFi. But after a few minutes of drawing my flow, I saw that the component ConvertJSONToSQL was replacing the underscore ('_') from the field name in the where condition (I was preparing an Update SQL). That was weird because, at the set …</p>Maurício Camargo SipmannWed, 02 Dec 2020 14:00:00 -0300tag:www.sipmann.com,2020-12-02:/en/apache-nifi-json-to-sql-replacing-underscore.htmlToolsApache NifiConvertJSONToSQLreplacing underscoreBlocking a user on SQL Server based on a schedulehttps://www.sipmann.com/en/blocking-user-on-sql-server-based-on-schedule.html<p>Ok, some time ago, I've posted about how you can set limits to connections on SQL Server using the <a href="https://www.sipmann.com/limiting-connection-resources-sql-server.html#.X6Cz8IhKhPY">Resource Governor</a>. But what if you can't use it? You always can block logins using a login trigger, but I don't like the idea of having selects running on every login …</p>Maurício Camargo SipmannSat, 14 Nov 2020 07:00:00 -0300tag:www.sipmann.com,2020-11-14:/en/blocking-user-on-sql-server-based-on-schedule.htmlSQL ServerSQLServerUserTime Schedule blockingHow to set columns on select using Entity Frameworkhttps://www.sipmann.com/en/select_specific_fields_with_efcore.html<p>So, you use Entity Framework Core, and you usually code your selects like the following, maybe you are getting too much data.</p> +<div class="highlight"><pre><span></span><code><span class="kt">var</span> <span class="n">products</span> <span class="p">=</span> <span class="n">Products</span> + <span class="p">.</span><span class="n">Where</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span> <span class="p">&gt;</span> <span class="m">0</span><span class="p">)</span> + <span class="p">.</span><span class="n">OrderBy</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">)</span> + <span class="p">.</span><span class="n">ToList</span><span class="p">()</span> +</code></pre></div> + +<p>Running the query above, on my table, you'll get the following output, take a look …</p>Maurício Camargo SipmannWed, 28 Oct 2020 19:00:00 -0300tag:www.sipmann.com,2020-10-28:/en/select_specific_fields_with_efcore.html.NETDotNetDotNet CoreEntity FrameworkEF CoreSpecify columnsZabbix Running on Low Memory Modehttps://www.sipmann.com/en/zabbix-running-on-low-memory-mode.html<p>Hey folks, another Zabbix post today. This one it's about increasing the Zabbix Server Cache. It's pretty common (if you have the default settings only) get a warning about your <code>Zabbix value cache running on low memory mode</code> at your dashboard or logs.</p> +<p><img alt="Zabbix Dashboard warning about the memory problem" src="/images/zabbix_low_memory_mode.png"> +<img alt="Zabbix Dashboard cache graph 70% used" src="/images/zabbix_cache_filling.png"></p> +<p>To solve, go back to your Zabbix …</p>Maurício Camargo SipmannTue, 20 Oct 2020 19:00:00 -0300tag:www.sipmann.com,2020-10-20:/en/zabbix-running-on-low-memory-mode.htmlLinuxZabbixShellLow memoryCacheMonitoring MySQL Replication Status with PowerShellhttps://www.sipmann.com/en/monitoring-mysql-replication-with-powershell.html<p>I've been migration some bash scripts that I have to PowerShell, and it's time to migrate a script that monitors the replication of a MySQL database. The credit for the original script goes to <a href="https://handyman.dulare.com/mysql-replication-status-alerts-with-bash-script/">Paweł</a>. It's a simple script where I seek a few tags/fields that we get from …</p>Maurício Camargo SipmannWed, 14 Oct 2020 19:00:00 -0300tag:www.sipmann.com,2020-10-14:/en/monitoring-mysql-replication-with-powershell.htmlPowerShellMySQLMySQL ReplicationPowerShellPowershell mailMicrosoft Against Covidhttps://www.sipmann.com/en/microsoft-against-covid.html<p>Has your job been affected by covid? Well, last week I've posted on <a href="https://grepora.com/2020/09/17/microsoft-ignite-certification-voucher/">Grepora</a> about a Free Certification Voucher that Microsoft was giving away at the Microsoft Ignite event. After that, I found that they were also giving a huge discount to people who have had their job affected by …</p>Maurício Camargo SipmannSat, 03 Oct 2020 19:00:00 -0300tag:www.sipmann.com,2020-10-03:/en/microsoft-against-covid.htmlAzureAzureCertificationMicrosoftThe power of PowerShellhttps://www.sipmann.com/en/the-power-of-powershell.html<p>As a long time Linux user, I've automated a few things with bash scripts and stayed away from PowerShell... I've moved to a Windows environment a few years ago and still, haven gave a shot to PS. But why not? I've made a few scripts to automate some tasks at …</p>Maurício Camargo SipmannMon, 21 Sep 2020 19:00:00 -0300tag:www.sipmann.com,2020-09-21:/en/the-power-of-powershell.htmlPowerShellAzurePowerShellScriptGetChild-ItemRemove-ItemStop-ProccessTop Level Statement in C# 9https://www.sipmann.com/en/top_level_statement_csharp_9.html<p>Hey folks, I'm coming along to tell you a few things about the new feature of C# 9. Every time you want to start a new project, you always have the same Main File, with the same structure. At the next version of C# (version 9), we'll have a new …</p>Maurício Camargo SipmannWed, 29 Jul 2020 19:00:00 -0300tag:www.sipmann.com,2020-07-29:/en/top_level_statement_csharp_9.html.NETC#Dotnet CoreDotNet.netZabbix poller processes more than 75%https://www.sipmann.com/en/zabbix-poller-processes-more-than-75.html<p>Hey folks, this is the third post about tweaking the Zabbix configurations. All changes that I've suggested here were based on a Zabbix Server with 50+ hosts. Another thing that can happen to your server, it's the poller get overwhelmed by the amount of servers that need to be polled …</p>Maurício Camargo SipmannThu, 02 Jul 2020 19:00:00 -0300tag:www.sipmann.com,2020-07-02:/en/zabbix-poller-processes-more-than-75.htmlLinuxZabbixShellZabbix PollerPoller proccess more than 75%Monitoring a Website heath with Azure Functionshttps://www.sipmann.com/en/monitoring-website-heath-with-azure-functions.html<p>Sometimes you get your self in need to monitor a website's health or it's content for changes. Of course, there's plenty of options out there, but for the sake of curiosity, let's code our own to see what we can do. First things first. Everything you'll see here, you can …</p>Maurício Camargo SipmannMon, 22 Jun 2020 19:00:00 -0300tag:www.sipmann.com,2020-06-22:/en/monitoring-website-heath-with-azure-functions.htmlAzureAzureAzure DevopsC#Dotnet CoreDotNetMonitor WebsiteAzure Data Fundamentals certification with 80% discounthttps://www.sipmann.com/en/azure-data-fundamentals-certification-80-discount.html<p>Hey folks, if you want to achieve some certification this year, keep an eye open for vouchers. A few months ago, Oracle released a set of free courses with certifications. Now it's Microsoft time. Microsoft is updating they're certifications and we have a voucher of 80% discount using the coupon …</p>Maurício Camargo SipmannTue, 09 Jun 2020 12:30:00 -0300tag:www.sipmann.com,2020-06-09:/en/azure-data-fundamentals-certification-80-discount.htmlAzureAzureAzure FundamentalsAzure CertificationDiscountZabbix ICMP pinger processes more than 75%https://www.sipmann.com/en/zabbix-icmp-pinger-processes-more-than-75.html<p>So your monitoring sytems have grown and your zabbix started loggin "Zabbix icmp pinger processes more than 75% busy" at the dashboard.</p> +<p><img alt="Dashboard do zabbix avisando sobre o erro" src="/images/zabbix_pinger01.png"></p> +<p>All you have to do is open your config file (<code>/etc/zabbix/zabbix_server.conf</code>) and find the a tag named <code>StartPingers</code>. It'll be commented by default. Uncomment it …</p>Maurício Camargo SipmannMon, 25 May 2020 16:00:00 -0300tag:www.sipmann.com,2020-05-25:/en/zabbix-icmp-pinger-processes-more-than-75.htmlLinuxZabbixicmp pingericmp pinger more than 75Zabbix ServerZabbix Server Out of Memoryhttps://www.sipmann.com/en/zabbix-server-out-of-memory-crash.html<p>Do you have a crashing Zabbix Server and looking through the log <code>/var/log/zabbix/zabbix_server.log</code> you see the following out of memory message?</p> +<div class="highlight"><pre><span></span><code>__mem_malloc: skipped <span class="m">0</span> asked <span class="m">24</span> skip_min <span class="m">18446744073709551615</span> skip_max <span class="m">0</span> +<span class="o">[</span>file:dbconfig.c,line:94<span class="o">]</span> __zbx_mem_realloc<span class="o">()</span>: out of memory <span class="o">(</span>requested <span class="m">16</span> bytes<span class="o">)</span> +<span class="o">[</span>file:dbconfig.c,line …</code></pre></div>Maurício Camargo SipmannThu, 27 Feb 2020 19:00:00 -0300tag:www.sipmann.com,2020-02-27:/en/zabbix-server-out-of-memory-crash.htmlLinuxZabbixShellOut of memoryCrashFlutter + firebase auth crashinghttps://www.sipmann.com/en/flutter_with_firebase_auth_crashing.html<p>Hey Folks, recently I've started learning <a href="https://flutter.dev/">Flutter</a> and right after a TODO List, I tried a Firebase integration. But as soon as I started setting the dependencies, my app stopped opening... just a crash. After a few logs digging, I've found the following log.</p> +<div class="highlight"><pre><span></span><code>AndroidRuntime: FATAL EXCEPTION: main +AndroidRuntime: Process …</code></pre></div>Maurício Camargo SipmannThu, 03 Oct 2019 19:00:00 -0300tag:www.sipmann.com,2019-10-03:/en/flutter_with_firebase_auth_crashing.htmlFlutterflutterfirebaseArrayMapNoClassDefFoundRemoving a user from SQL Server database who owns a schemahttps://www.sipmann.com/en/removing-user-from-sql-server-database.html<p>Your customer urge you to drop a user from the MsSQL Server database, but you stuck with the following related error:</p> +<div class="highlight"><pre><span></span><code><span class="n">Error</span><span class="o">:</span> <span class="mi">15138</span> <span class="n">The</span> <span class="n">database</span> <span class="n">principal</span> <span class="n">owns</span> <span class="n">a</span> <span class="n">schema</span> <span class="k">in</span> <span class="n">the</span> <span class="n">database</span><span class="o">,</span> <span class="n">and</span> <span class="n">cannot</span> <span class="n">be</span> <span class="n">dropped</span><span class="o">.</span> +</code></pre></div> + +<p>That means that the user owns one or more shcemas of your database. If …</p>Maurício Camargo SipmannFri, 06 Sep 2019 07:00:00 -0300tag:www.sipmann.com,2019-09-06:/en/removing-user-from-sql-server-database.htmlSQL ServerSQLServerUserThe database principal owns a schemaLimiting Connection Resources on SQL Serverhttps://www.sipmann.com/en/limiting-connection-resources-sql-server.html<p>Have you ever suffered from a slow SQLServer database? Someone love to run that heavy query in the database? Resource Governor to the rescue. You can set a few rules on how users (connections actually) will use the server/database resources based on a few things.</p> +<p>First things first, if …</p>Maurício Camargo SipmannMon, 12 Aug 2019 12:00:00 -0300tag:www.sipmann.com,2019-08-12:/en/limiting-connection-resources-sql-server.htmlSQL ServerSQLServerResource GovernorUsing git hooks to easy your lifehttps://www.sipmann.com/en/using_git_hooks_easy_your_life.html<p>Hey folks, it's been a time since my last post. In the meantime, I moved to another state, changed job, and started learning new kinds of stuff. Today I would like to share one thing that I usually do with my small git projects. Git has many cool features, git …</p>Maurício Camargo SipmannTue, 30 Jul 2019 20:00:00 -0300tag:www.sipmann.com,2019-07-30:/en/using_git_hooks_easy_your_life.htmltoolsgitshellpre-commithooksMicroservices with NodeJS, Express.js and RabbitMQ Part 2https://www.sipmann.com/en/microservices_nodejs_express_rabbitmq_part_2.html<p>If you haven't read the <a class="reference external" href="https://www.sipmann.com/microservices_nodejs_express_rabbitmq_part_1-en.html">part 1</a> go ahead and read it... It can be useful :). Or if for some reason you want to start now, you can grab the project where we stopped <a class="reference external" href="https://github.com/sipmann/imagecompacter/releases/tag/v1">here</a> and get along. On this part, we'll implement the RabbitMQ queue and see how we …</p>Maurício Camargo SipmannFri, 13 Apr 2018 13:00:00 -0300tag:www.sipmann.com,2018-04-13:/en/microservices_nodejs_express_rabbitmq_part_2.htmlFront-endnodejsmicroservicesrabbitmqexpressjsimageminimagemin-pngquantnode jsMicroservices with NodeJS, Express.js and RabbitMQ Part 1https://www.sipmann.com/en/microservices_nodejs_express_rabbitmq_part_1.html<p>This is the first part of a microservices development series. The service will consist of the bellow architecture, where we will expose an image optimizer service that will forward the request to a <a class="reference external" href="https://www.rabbitmq.com/">RabbitMQ</a> queue and answer with the bytecode of the optimized image. It shouldn't be a long series …</p>Maurício Camargo SipmannWed, 04 Apr 2018 11:25:00 -0300tag:www.sipmann.com,2018-04-04:/en/microservices_nodejs_express_rabbitmq_part_1.htmlFront-endnodejsmicroservicesrabbitmqexpressjsimageminimagemin-pngquantnode jsConnecting to a database through SSHhttps://www.sipmann.com/en/connecting_to_database_through_ssh.html<p>If someday, for some reason, you need to establish a connection with a database which is behind a firewall and you only have SSH access on that server (and you don't want to use a CLI) you can do an SSH tunnel. It's pretty simple, bellow has a sample of …</p>Maurício Camargo SipmannThu, 29 Mar 2018 10:03:00 -0300tag:www.sipmann.com,2018-03-29:/en/connecting_to_database_through_ssh.htmlLinuxopensshtunnelssh tunnelsshthrough firewallNow posting on Greporahttps://www.sipmann.com/en/now_posting_on_grepora.html<p>A few weeks ago I started posting at <a class="reference external" href="https://grepora.com/blog/">Grepora</a> blog. If you like or are looking for some Oracle related stuff, Grepora it's a good place to go and spend a time reading :). From time to time I'll be posting there, it doesn't mean that this blog will be closed …</p>Maurício Camargo SipmannSat, 24 Mar 2018 00:40:00 -0300tag:www.sipmann.com,2018-03-24:/en/now_posting_on_grepora.htmlRandomGreporaRandomScaffolding a React app with Parcel and Yeomanhttps://www.sipmann.com/en/scaffolding_react_app_with_parcel_yeoman.html<p>Since <a class="reference external" href="https://parceljs.org/">Parcel JS</a> arrived, I've been using it a lot as an awesome alternative for WebPack. Webpack isn't bad but IMO it's too complex for the job and parcel do the same (at least the basic) with almost zero configuration. But if you need to create many apps (like a …</p>Maurício Camargo SipmannSat, 17 Mar 2018 13:00:00 -0300tag:www.sipmann.com,2018-03-17:/en/scaffolding_react_app_with_parcel_yeoman.htmlFront-endnodejsyeomanparcelreactCould not open connection with MySQL and Hibernatehttps://www.sipmann.com/en/cloud-not-open-connection-java-mysql-hibernate.html<p>Last day I decided to deploy a MySQL Docker image to work with my Java application. I've been using PostgreSQL instead and have no problems at all, but after I moved to MySQL, the app didn't connect anymore with the database and throw some &quot;Could not open connection&quot; at my …</p>Maurício Camargo SipmannFri, 09 Mar 2018 12:35:00 -0300tag:www.sipmann.com,2018-03-09:/en/cloud-not-open-connection-java-mysql-hibernate.htmlJavaJavaMySQLHibernateSolving java.net.SocketException: Protocol family unavailable on a Java + Docker + WildFlyhttps://www.sipmann.com/en/socketException-protocol-family-unavailable-java-docker-wildfly.html<p>On the last days I've been playing with <a class="reference external" href="http://wildfly-swarm.io/">WildFly Swarm</a> and I decided to deploy a simple app with Docker. Should work fine, at least that was what I thought. Built a container with the following Dockerfile and instead of a working web app, all that I got was the …</p>Maurício Camargo SipmannSun, 04 Mar 2018 17:40:00 -0300tag:www.sipmann.com,2018-03-04:/en/socketException-protocol-family-unavailable-java-docker-wildfly.htmlJavaJavaWildFlyDockerjava.net.SocketExceptionProtocol family unavailableChange display settings on linux with Disperhttps://www.sipmann.com/en/linux-external-display-with-disper.html<p>From time to time, I change the Linux distro on my laptop or just do a fresh install on it. And once in a while, have random problems with external displays. It can be something really &quot;simple&quot; like don't detecting the external monitor or something crazy like the image below …</p>Maurício Camargo SipmannTue, 27 Feb 2018 12:40:00 -0300tag:www.sipmann.com,2018-02-27:/en/linux-external-display-with-disper.htmlLinuxLinuxexternal displaydisperJava - Files.readAllBytes throws OutOfMemoryhttps://www.sipmann.com/en/reading-files-java-readAllBytes-outofmemory.html<p>When you need to interact with files, there's the possibility to read all bytes from the file with <cite>Files.readAllBytes</cite>. But be aware of the kinds of files your application will deal with because the Java API files have a limit for the buffer that is defined as <cite>Integer.MAX_VALUE …</cite></p>Maurício Camargo SipmannSat, 17 Feb 2018 13:00:00 -0200tag:www.sipmann.com,2018-02-17:/en/reading-files-java-readAllBytes-outofmemory.htmlJavaJavaFiles.readAllBytesoutOfMemory \ No newline at end of file diff --git a/en/feeds/mauricio-camargo-sipmann.rss.xml.gz b/en/feeds/mauricio-camargo-sipmann.rss.xml.gz new file mode 100644 index 000000000..3ec39e8d0 Binary files /dev/null and b/en/feeds/mauricio-camargo-sipmann.rss.xml.gz differ diff --git a/en/feeds/mysql.atom.xml b/en/feeds/mysql.atom.xml new file mode 100644 index 000000000..e6787797a --- /dev/null +++ b/en/feeds/mysql.atom.xml @@ -0,0 +1,14 @@ + +Sipmann - MySQLhttps://www.sipmann.com/en/2020-12-09T13:40:00-03:00Changing a MySQL user password across multiple application instances without downtime2020-12-09T13:40:00-03:002020-12-09T13:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-12-09:/en/mysql-dual-password-functionality.html<p>Do you need to change the password of a MySQL user that it's being used in an application, and can't allow a single downtime? Well, MySQL 8.0.14 came with a feature called <a href="https://dev.mysql.com/doc/refman/8.0/en/password-management.html#dual-passwords">Dual Password Support</a>, with it you can change the password keeping the previous password as a …</p><p>Do you need to change the password of a MySQL user that it's being used in an application, and can't allow a single downtime? Well, MySQL 8.0.14 came with a feature called <a href="https://dev.mysql.com/doc/refman/8.0/en/password-management.html#dual-passwords">Dual Password Support</a>, with it you can change the password keeping the previous password as a kind of backup. That way you still can log in using the old password or can start using the new one. With that, the password change workflow it's the following.</p> +<p>1) Change password keeping the old one;</p> +<p>2) Deploy the new config to your app/cluster;</p> +<p>3) Discard the old password.</p> +<p>To change the password and keep the old one, you have the following command.</p> +<div class="highlight"><pre><span></span><code><span class="k">ALTER</span> <span class="n">USER</span> <span class="s1">&#39;appuser&#39;</span><span class="o">@</span><span class="s1">&#39;localhost&#39;</span> <span class="n">IDENTIFIED</span> <span class="k">BY</span> <span class="s1">&#39;new_password&#39;</span> <span class="n">RETAIN</span> <span class="n">CURRENT</span> <span class="n">PASSWORD</span><span class="p">;</span> +</code></pre></div> + +<p>To discard the old one, run the following.</p> +<div class="highlight"><pre><span></span><code><span class="k">ALTER</span> <span class="n">USER</span> <span class="s1">&#39;appuser&#39;</span><span class="o">@</span><span class="s1">&#39;localhost&#39;</span> <span class="n">DISCARD</span> <span class="n">OLD</span> <span class="n">PASSWORD</span><span class="p">;</span> +</code></pre></div> + +<p>And you are done. Hope you find it as useful as I :)</p> \ No newline at end of file diff --git a/en/feeds/mysql.atom.xml.gz b/en/feeds/mysql.atom.xml.gz new file mode 100644 index 000000000..fc1254633 Binary files /dev/null and b/en/feeds/mysql.atom.xml.gz differ diff --git a/en/feeds/net.atom.xml b/en/feeds/net.atom.xml new file mode 100644 index 000000000..df9f9fb59 --- /dev/null +++ b/en/feeds/net.atom.xml @@ -0,0 +1,59 @@ + +Sipmann - .NEThttps://www.sipmann.com/en/2020-10-28T19:00:00-03:00How to set columns on select using Entity Framework2020-10-28T19:00:00-03:002020-10-28T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-28:/en/select_specific_fields_with_efcore.html<p>So, you use Entity Framework Core, and you usually code your selects like the following, maybe you are getting too much data.</p> +<div class="highlight"><pre><span></span><code><span class="kt">var</span> <span class="n">products</span> <span class="p">=</span> <span class="n">Products</span> + <span class="p">.</span><span class="n">Where</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span> <span class="p">&gt;</span> <span class="m">0</span><span class="p">)</span> + <span class="p">.</span><span class="n">OrderBy</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">)</span> + <span class="p">.</span><span class="n">ToList</span><span class="p">()</span> +</code></pre></div> + +<p>Running the query above, on my table, you'll get the following output, take a look …</p><p>So, you use Entity Framework Core, and you usually code your selects like the following, maybe you are getting too much data.</p> +<div class="highlight"><pre><span></span><code><span class="kt">var</span> <span class="n">products</span> <span class="p">=</span> <span class="n">Products</span> + <span class="p">.</span><span class="n">Where</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span> <span class="p">&gt;</span> <span class="m">0</span><span class="p">)</span> + <span class="p">.</span><span class="n">OrderBy</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">)</span> + <span class="p">.</span><span class="n">ToList</span><span class="p">()</span> +</code></pre></div> + +<p>Running the query above, on my table, you'll get the following output, take a look at how many columns you are getting back from your database.</p> +<p><img alt="Screenshot with every single column" src="/images/ef_core_allcolumns.png"></p> +<p>In my case, I only care about the Title, PublishedData, and a small description. So to get back only these fields, we have a few options. In the first one, we'll set the fields and return them as a dynamic object, the second one, is to give the .NET a class to use. </p> +<div class="highlight"><pre><span></span><code><span class="kt">var</span> <span class="n">products</span> <span class="p">=</span> <span class="n">Products</span> + + <span class="p">.</span><span class="n">Select</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="k">new</span> <span class="p">{</span><span class="n">p</span><span class="p">.</span><span class="n">ProductID</span><span class="p">,</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">,</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span><span class="p">,</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitPrice</span><span class="p">})</span> + <span class="c1">//.Select(p =&gt; new ProductDTO {p.ProductID, p.ProductName, p.UnitsInStock, p.UnitPrice})</span> + + <span class="p">.</span><span class="n">Where</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span> <span class="p">&gt;</span> <span class="m">0</span><span class="p">)</span> + <span class="p">.</span><span class="n">OrderBy</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">)</span> + <span class="p">.</span><span class="n">ToList</span><span class="p">()</span> +</code></pre></div> + +<p><img alt="Screenshot with fewer columns and also fewer data size" src="/images/ef_core_less_columns.png"></p>Top Level Statement in C# 92020-07-29T19:00:00-03:002020-07-29T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-07-29:/en/top_level_statement_csharp_9.html<p>Hey folks, I'm coming along to tell you a few things about the new feature of C# 9. Every time you want to start a new project, you always have the same Main File, with the same structure. At the next version of C# (version 9), we'll have a new …</p><p>Hey folks, I'm coming along to tell you a few things about the new feature of C# 9. Every time you want to start a new project, you always have the same Main File, with the same structure. At the next version of C# (version 9), we'll have a new feature called <code>Top Level Statement</code>. With that, we'll be able to code our app without any namespace/class/public void static main structure. Take a look at the code below.</p> +<div class="highlight"><pre><span></span><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span> + +<span class="n">Console</span><span class="p">.</span><span class="n">WriteLine</span><span class="p">(</span><span class="s">&quot;Hello World!&quot;</span><span class="p">);</span> +</code></pre></div> + +<p>It looks pretty simple, but with this, you can play around with your code, and even code a simple/tiny Web API. To start playing with the new features, firstly download the <a href="https://dotnet.microsoft.com/download/dotnet/5.0">.net 5 SDK</a> and change your <code>.csproj</code> file to target the .net 5 and language preview like bellow.</p> +<div class="highlight"><pre><span></span><code><span class="nt">&lt;Project</span> <span class="na">Sdk=</span><span class="s">&quot;Microsoft.NET.Sdk&quot;</span><span class="nt">&gt;</span> + <span class="nt">&lt;PropertyGroup&gt;</span> + <span class="nt">&lt;OutputType&gt;</span>Exe<span class="nt">&lt;/OutputType&gt;</span> + <span class="nt">&lt;TargetFramework&gt;</span>net5.0<span class="nt">&lt;/TargetFramework&gt;</span> + <span class="nt">&lt;LangVersion&gt;</span>preview<span class="nt">&lt;/LangVersion&gt;</span> + <span class="nt">&lt;/PropertyGroup&gt;</span> +<span class="nt">&lt;/Project&gt;</span> +</code></pre></div> + +<p>And you're ready to play with the awesome features available in the preview. Let's code a way to get the image of the day from NASA API and print the Picture of the Day. No awesome code here, it's really a way to show how simple a simple call could be. After here, why not save the image in a file? Maybe send the file over telegram?</p> +<div class="highlight"><pre><span></span><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Net.Http</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Text.Json</span><span class="p">;</span> + +<span class="kt">var</span> <span class="n">API</span> <span class="p">=</span> <span class="s">&quot;https://api.nasa.gov/planetary/apod?hd=true&amp;api_key=DEMO_KEY&quot;</span><span class="p">;</span> +<span class="kt">var</span> <span class="n">cli</span> <span class="p">=</span> <span class="k">new</span> <span class="n">HttpClient</span><span class="p">();</span> + +<span class="kt">var</span> <span class="n">response</span> <span class="p">=</span> <span class="k">await</span> <span class="n">cli</span><span class="p">.</span><span class="n">GetAsync</span><span class="p">(</span><span class="n">API</span><span class="p">);</span> +<span class="kt">var</span> <span class="n">data</span> <span class="p">=</span> <span class="n">JsonSerializer</span><span class="p">.</span><span class="n">Deserialize</span><span class="p">&lt;</span><span class="n">NasaApi</span><span class="p">&gt;(</span><span class="k">await</span> <span class="n">response</span><span class="p">.</span><span class="n">Content</span><span class="p">.</span><span class="n">ReadAsStringAsync</span><span class="p">());</span> + +<span class="n">Console</span><span class="p">.</span><span class="n">WriteLine</span><span class="p">(</span><span class="n">data</span><span class="p">.</span><span class="n">Url</span><span class="p">);</span> +</code></pre></div> + +<p>That's it for today folks. Keep an eye open for the awesome features C# 9 will bring to us, there's plenty more features already available.</p> \ No newline at end of file diff --git a/en/feeds/net.atom.xml.gz b/en/feeds/net.atom.xml.gz new file mode 100644 index 000000000..c6451af92 Binary files /dev/null and b/en/feeds/net.atom.xml.gz differ diff --git a/en/feeds/powershell.atom.xml b/en/feeds/powershell.atom.xml new file mode 100644 index 000000000..5f8361e46 --- /dev/null +++ b/en/feeds/powershell.atom.xml @@ -0,0 +1,124 @@ + +Sipmann - PowerShellhttps://www.sipmann.com/en/2020-12-21T13:30:00-03:00Monitoring MySQL restarts with PowerShell2020-12-21T13:30:00-03:002020-12-21T13:30:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-12-21:/en/monitoring-mysql-restarts-with-powershell.html<p>Hey folks, it's time for another PowerShell script. If you haven't seen the other ones, check the links below.</p> +<ul> +<li><a href="https://www.sipmann.com/en/monitoring-mysql-replication-with-powershell.html">Monitoring MySQL replication with PowerShell</a></li> +</ul> +<p>Well, this one it's a pretty simple script, but again, if your customer doesn't have a Zabbix server or doesn't allow you to setup one to …</p><p>Hey folks, it's time for another PowerShell script. If you haven't seen the other ones, check the links below.</p> +<ul> +<li><a href="https://www.sipmann.com/en/monitoring-mysql-replication-with-powershell.html">Monitoring MySQL replication with PowerShell</a></li> +</ul> +<p>Well, this one it's a pretty simple script, but again, if your customer doesn't have a Zabbix server or doesn't allow you to setup one to do the monitoring, a set of scripts can be handy. We start executing some basic query <code>SHOW GLOBAL STATUS LIKE 'Uptime'</code>, with that we'll get exactly what we're looking for.</p> +<p>If for some reason, the command fails (watch for the "global" variable called <code>$lastExitCode</code>), we send an e-mail telling you about that connection problem.</p> +<p>And then, we get to the part where we parse the value, this one is pretty similar to the parse we did on the first post about using PowerShell to monitor MySQL. But we basically look for the Value line, split it by space and then parse the second position to an integer. And then all we have to do is check if the uptime is lower than our threshold, if it is we send an e-mail.</p> +<div class="highlight"><pre><span></span><code><span class="nv">$MailFrom</span> <span class="p">=</span> <span class="s1">&#39;maurio[at]sipmann.com&#39;</span> +<span class="nv">$MailTo</span> <span class="p">=</span> <span class="s1">&#39;mauricio[at]sipmann.com&#39;</span> +<span class="nv">$MysqlHost</span> <span class="p">=</span> <span class="s1">&#39;127.0.0.1&#39;</span> +<span class="nv">$MysqlUser</span> <span class="p">=</span> <span class="s1">&#39;root&#39;</span> +<span class="nv">$MysqlPass</span> <span class="p">=</span> <span class="s1">&#39;123&#39;</span> + + +<span class="nv">$data</span> <span class="p">=</span> <span class="p">$(</span><span class="n">mysql</span> <span class="n">-h</span> <span class="nv">$MysqlHost</span> <span class="n">-u</span> <span class="nv">$MysqlUser</span> <span class="n">-p</span><span class="s2">&quot;$MysqlPass&quot;</span> <span class="n">-e</span> <span class="s2">&quot;SHOW GLOBAL STATUS LIKE &#39;Uptime&#39; \G&quot;</span><span class="p">)</span> + +<span class="cm">&lt;# Unable to execute the sql Command #&gt;</span> +<span class="k">if</span> <span class="p">(</span><span class="nv">$lastExitCode</span> <span class="o">-eq</span> <span class="n">1</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Send-MailMessage</span> <span class="n">-To</span> <span class="nv">$MailTo</span> <span class="n">-From</span> <span class="nv">$MailFrom</span> <span class="n">-Subject</span> <span class="s1">&#39;Connection problem&#39;</span> <span class="n">-bodyAsHtml</span> <span class="s2">&quot;Connection problem on host ${MysqlHost}&quot;</span> <span class="n">-Credential</span> <span class="nb">Get-Credential</span> <span class="n">-SmtpServer</span> <span class="s1">&#39;smtp.office365.com&#39;</span> <span class="n">-Port</span> <span class="n">587</span> <span class="n">-UseSsl</span> + <span class="n">exit</span> +<span class="p">}</span> + +<span class="nv">$UpTime</span> <span class="p">=</span> <span class="no">[int]</span><span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Value:&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> + +<span class="cm">&lt;# If the uptime is lower then 20 minutes #&gt;</span> +<span class="k">if</span> <span class="p">(</span><span class="nv">$UpTime</span> <span class="o">-lt</span> <span class="n">1200</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Send-MailMessage</span> <span class="n">-To</span> <span class="nv">$MailTo</span> <span class="n">-From</span> <span class="nv">$MailFrom</span> <span class="n">-Subject</span> <span class="s2">&quot;MySQL Restarted&quot;</span> <span class="n">-bodyAsHtml</span> <span class="s2">&quot;MySQL host ${MysqlHost} restarted less than 20 minutes ago&quot;</span> <span class="n">-Credential</span> <span class="nb">Get-Credential</span> <span class="n">-SmtpServer</span> <span class="s1">&#39;smtp.office365.com&#39;</span> <span class="n">-Port</span> <span class="n">587</span> <span class="n">-UseSsl</span> +<span class="p">}</span> +</code></pre></div> + +<p>This script (and the other ones I use) is available at my GitHub <a href="https://github.com/sipmann/PowerShellScripts">here</a>. Keep in mind that the ones on the GitHub repo, are a little different from here.</p>Monitoring MySQL Replication Status with PowerShell2020-10-14T19:00:00-03:002020-10-14T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-14:/en/monitoring-mysql-replication-with-powershell.html<p>I've been migration some bash scripts that I have to PowerShell, and it's time to migrate a script that monitors the replication of a MySQL database. The credit for the original script goes to <a href="https://handyman.dulare.com/mysql-replication-status-alerts-with-bash-script/">Paweł</a>. It's a simple script where I seek a few tags/fields that we get from …</p><p>I've been migration some bash scripts that I have to PowerShell, and it's time to migrate a script that monitors the replication of a MySQL database. The credit for the original script goes to <a href="https://handyman.dulare.com/mysql-replication-status-alerts-with-bash-script/">Paweł</a>. It's a simple script where I seek a few tags/fields that we get from <code>SHOW SLAVE STATUS\G</code> command, the fields are. <code>Slave_IO_Running</code>, <code>Slave_SQL_Running</code>, and <code>Seconds_Behind_Master</code>. I still need to figure out the proper way to store/read variables like usernames and passwords, if you have any tips, feel free to even make a pull request (<a href="https://github.com/sipmann/PowerShellScripts">here</a>) at the git where I'll store some scripts.</p> +<div class="highlight"><pre><span></span><code><span class="cm">&lt;#</span> +<span class="cm"> Variables definition</span> +<span class="cm">#&gt;</span> +<span class="nv">$MaxSeconds</span> <span class="p">=</span> <span class="n">120</span> <span class="c"># Max seconds behind master allowed</span> +<span class="nv">$MysqlUser</span> <span class="p">=</span> <span class="s1">&#39;root&#39;</span> +<span class="nv">$MysqlPass</span> <span class="p">=</span> <span class="s1">&#39;&#39;</span> + +<span class="nv">$MailTo</span> <span class="p">=</span> <span class="s1">&#39;mauricio@sipmann.com&#39;</span> +<span class="nv">$MailFrom</span> <span class="p">=</span> <span class="s1">&#39;mauricio@sipmann.com&#39;</span> + + +<span class="nv">$data</span> <span class="p">=</span> <span class="p">$(</span><span class="n">mysql</span> <span class="n">-u</span> <span class="nv">$MysqlUser</span> <span class="n">-p</span><span class="s2">&quot;$MysqlPass&quot;</span> <span class="n">-e</span> <span class="s1">&#39;SHOW SLAVE STATUS \G&#39;</span><span class="p">)</span> + +<span class="c">#Debug data</span> +<span class="c">#$data = Get-Content &#39;c:\temp\sampleresult.txt&#39;</span> + +<span class="cm">&lt;# Parse the data #&gt;</span> +<span class="nv">$IORunning</span> <span class="p">=</span> <span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Slave_IO_Running:&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> +<span class="nv">$SQLRunning</span> <span class="p">=</span> <span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Slave_SQL_Running:&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> +<span class="nv">$LastErrNo</span> <span class="p">=</span> <span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Last_Errno&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> +<span class="nv">$SecondsBh</span> <span class="p">=</span> <span class="no">[int]</span><span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Seconds_Behind_Master&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> + +<span class="k">If</span> <span class="p">(</span><span class="nv">$IORunning</span> <span class="o">-Eq</span> <span class="s1">&#39;No&#39;</span> <span class="o">-Or</span> <span class="nv">$SQLRunning</span> <span class="o">-Eq</span> <span class="s1">&#39;No&#39;</span> <span class="o">-Or</span> <span class="nv">$SecondsBh</span> <span class="o">-gt</span> <span class="nv">$MaxSeconds</span><span class="p">)</span> <span class="p">{</span> + <span class="nv">$MailBody</span> <span class="p">=</span> <span class="s1">&#39;&lt;h1&gt;Problema na replicação&lt;/h1&gt;&lt;br&gt;&#39;</span> + + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39; IO Running: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$IORunning</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39; SQL Running: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$SQLRunning</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39;Seconds Behind: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$SecondsBh</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39; Last Err No: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$LastErrNo</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + + <span class="cm">&lt;# Send e-mail, maybe some telegram message here too #&gt;</span> + <span class="nb">Send-MailMessage</span> <span class="n">-To</span> <span class="nv">$MailTo</span> <span class="n">-From</span> <span class="nv">$MailFrom</span> <span class="n">-Subject</span> <span class="s1">&#39;Problemas na replicação&#39;</span> <span class="n">-bodyAsHtml</span> <span class="nv">$MailBody</span> <span class="n">-Credential</span> <span class="p">(</span><span class="nb">Get-Credential</span><span class="p">)</span> <span class="n">-SmtpServer</span> <span class="s1">&#39;smtp.office365.com&#39;</span> <span class="n">-Port</span> <span class="n">587</span> <span class="n">-UseSsl</span> +<span class="p">}</span> <span class="k">Else</span> <span class="p">{</span> + <span class="nb">Write-Host</span> <span class="s2">&quot;Up and running&quot;</span> +<span class="p">}</span> +</code></pre></div>The power of PowerShell2020-09-21T19:00:00-03:002020-09-21T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-09-21:/en/the-power-of-powershell.html<p>As a long time Linux user, I've automated a few things with bash scripts and stayed away from PowerShell... I've moved to a Windows environment a few years ago and still, haven gave a shot to PS. But why not? I've made a few scripts to automate some tasks at …</p><p>As a long time Linux user, I've automated a few things with bash scripts and stayed away from PowerShell... I've moved to a Windows environment a few years ago and still, haven gave a shot to PS. But why not? I've made a few scripts to automate some tasks at a Protheus server.</p> +<p>I found the PS scripts being easy to read and understand. Bellow, we have a script to remove files filtering their extension (or no extension at all like the following script). </p> +<div class="highlight"><pre><span></span><code><span class="nb">Get-ChildItem</span> <span class="s2">&quot;C:\TOTVS\protheus_data\system&quot;</span> <span class="o">-File</span> <span class="n">-Filter</span> <span class="p">*.</span> <span class="p">|</span> <span class="nb">Move-Item</span> <span class="n">-Force</span> <span class="n">-Destination</span> <span class="p">{</span> + <span class="cm">&lt;# Diretory where the files will be moved. You can use Date formats to help name it #&gt;</span> + <span class="cm">&lt;# LastWriteTime proprtie from the current file #&gt;</span> + <span class="nv">$dir</span> <span class="p">=</span> <span class="s2">&quot;C:\bad_files\{0:yyyy\\MM\\dd}&quot;</span> <span class="o">-f</span> <span class="nv">$_</span><span class="p">.</span><span class="n">LastWriteTime</span> + <span class="nv">$null</span> <span class="p">=</span> <span class="n">mkdir</span> <span class="nv">$dir</span> <span class="n">-Force</span> + <span class="s2">&quot;$dir\</span><span class="p">$(</span><span class="nv">$_</span><span class="p">.</span><span class="n">Name</span><span class="p">)</span><span class="s2">&quot;</span> +<span class="p">}</span> +</code></pre></div> + +<p>Have you ever been in the need to remove files based on other file content? Bello a script where I read a file that has the names of files that I want to remove. </p> +<div class="highlight"><pre><span></span><code><span class="k">foreach</span><span class="p">(</span><span class="nv">$line</span> <span class="k">in</span> <span class="nb">Get-Content</span> <span class="p">.\</span><span class="n">Desktop</span><span class="p">\</span><span class="n">bad_files</span><span class="p">.</span><span class="n">txt</span><span class="p">)</span> <span class="p">{</span> + <span class="k">if</span> <span class="p">(</span><span class="nb">Test-Path</span><span class="p">(</span><span class="s1">&#39;\\x.y.z.a\c$\TOTVS\protheus_data\xmls\&#39;</span><span class="p">+</span><span class="nv">$line</span><span class="p">+</span><span class="s1">&#39;.xml&#39;</span><span class="p">))</span> <span class="p">{</span> + <span class="nb">Remove-Item</span><span class="p">(</span><span class="s1">&#39;\\x.y.z.a\c$\TOTVS\protheus_data\xmls\&#39;</span><span class="p">+</span><span class="nv">$line</span><span class="p">+</span><span class="s1">&#39;.xml&#39;</span><span class="p">)</span> + <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> + <span class="nb">echo </span><span class="nv">$line</span> <span class="p">+</span> <span class="s1">&#39; - File not found&#39;</span> + <span class="p">}</span> +<span class="p">}</span> +</code></pre></div> + +<p>And a bonus script to stop/start services (if you handle some Protheus Server, you know why I do that).</p> +<div class="highlight"><pre><span></span><code><span class="nv">$servicesNames</span> <span class="p">=</span> <span class="s1">&#39;app_main&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker1&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker2&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker3&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker4&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker5&#39;</span> + +<span class="nb">Write-host</span> <span class="s2">&quot;Stoping Services&quot;</span> +<span class="nb">Write-host</span> <span class="s2">&quot;--------------------------&quot;</span> + +<span class="k">foreach</span> <span class="p">(</span><span class="nv">$srv</span> <span class="k">in</span> <span class="nv">$servicesNames</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Write-host</span> <span class="s2">&quot;Stopping: &quot;</span> <span class="p">+</span> <span class="nv">$srv</span> + <span class="nv">$SrvPID</span> <span class="p">=</span> <span class="p">(</span><span class="nb">get-wmiobject</span> <span class="n">win32_service</span> <span class="p">|</span> <span class="nb">where </span><span class="p">{</span> <span class="nv">$_</span><span class="p">.</span><span class="n">name</span> <span class="o">-eq</span> <span class="nv">$srv</span><span class="p">}).</span><span class="n">processID</span> + <span class="nb">Write-host</span> <span class="s2">&quot;PID: &quot;</span> <span class="p">+</span> <span class="nv">$SrvPID</span> + + <span class="cm">&lt;# Force if the proccess is stucked #&gt;</span> + <span class="nb">Stop-Process</span> <span class="nv">$SrvPID</span> <span class="n">-Force</span> + <span class="nb">Write-host</span> <span class="s2">&quot;PDI &quot;</span> <span class="p">+</span> <span class="nv">$SrvPID</span> <span class="p">+</span> <span class="s2">&quot; stopped&quot;</span> +<span class="p">}</span> + + +<span class="nb">Write-host</span> <span class="s2">&quot;Starting Services&quot;</span> +<span class="nb">Write-host</span> <span class="s2">&quot;--------------------------&quot;</span> + +<span class="k">foreach</span> <span class="p">(</span><span class="nv">$srv</span> <span class="k">in</span> <span class="nv">$servicesNames</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Write-host</span> <span class="s2">&quot;Starting: &quot;</span> <span class="p">+</span> <span class="nv">$srv</span> + <span class="nb">Start-Service</span> <span class="nv">$srv</span> +<span class="p">}</span> +</code></pre></div> + +<p>Do you have any automated script? Share with us :)</p> \ No newline at end of file diff --git a/en/feeds/powershell.atom.xml.gz b/en/feeds/powershell.atom.xml.gz new file mode 100644 index 000000000..f6c281a5f Binary files /dev/null and b/en/feeds/powershell.atom.xml.gz differ diff --git a/en/feeds/random.atom.xml b/en/feeds/random.atom.xml new file mode 100644 index 000000000..19f08f5e4 --- /dev/null +++ b/en/feeds/random.atom.xml @@ -0,0 +1,3 @@ + +Sipmann - Randomhttps://www.sipmann.com/en/2018-03-24T00:40:00-03:00Now posting on Grepora2018-03-24T00:40:00-03:002018-03-24T00:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-03-24:/en/now_posting_on_grepora.html<p>A few weeks ago I started posting at <a class="reference external" href="https://grepora.com/blog/">Grepora</a> blog. If you like or are looking for some Oracle related stuff, Grepora it's a good place to go and spend a time reading :). From time to time I'll be posting there, it doesn't mean that this blog will be closed …</p><p>A few weeks ago I started posting at <a class="reference external" href="https://grepora.com/blog/">Grepora</a> blog. If you like or are looking for some Oracle related stuff, Grepora it's a good place to go and spend a time reading :). From time to time I'll be posting there, it doesn't mean that this blog will be closed or anything like that, but probably this one will be more focused on Front-end stuff, a few tricks with linux and a lil less with Java.</p> + \ No newline at end of file diff --git a/en/feeds/random.atom.xml.gz b/en/feeds/random.atom.xml.gz new file mode 100644 index 000000000..7c74b82c4 Binary files /dev/null and b/en/feeds/random.atom.xml.gz differ diff --git a/en/feeds/sql-server.atom.xml b/en/feeds/sql-server.atom.xml new file mode 100644 index 000000000..f5ccd3794 --- /dev/null +++ b/en/feeds/sql-server.atom.xml @@ -0,0 +1,184 @@ + +Sipmann - SQL Serverhttps://www.sipmann.com/en/2020-11-14T07:00:00-03:00Blocking a user on SQL Server based on a schedule2020-11-14T07:00:00-03:002020-11-14T07:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-11-14:/en/blocking-user-on-sql-server-based-on-schedule.html<p>Ok, some time ago, I've posted about how you can set limits to connections on SQL Server using the <a href="https://www.sipmann.com/limiting-connection-resources-sql-server.html#.X6Cz8IhKhPY">Resource Governor</a>. But what if you can't use it? You always can block logins using a login trigger, but I don't like the idea of having selects running on every login …</p><p>Ok, some time ago, I've posted about how you can set limits to connections on SQL Server using the <a href="https://www.sipmann.com/limiting-connection-resources-sql-server.html#.X6Cz8IhKhPY">Resource Governor</a>. But what if you can't use it? You always can block logins using a login trigger, but I don't like the idea of having selects running on every login. So I came across with a solution using a stored procedure, a table and the Agent.</p> +<p>The main idea is, store the time that a user must be blocked and using the Agent, disable or enable the user. Bellow you can see the table (the table is in Portuguese, but I have a few comment blocks to help you).</p> +<div class="highlight"><pre><span></span><code><span class="k">CREATE</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"> </span><span class="p">(</span><span class="w"></span> +<span class="w"> </span><span class="n">Id</span><span class="w"> </span><span class="nc">INT</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">LoginName</span><span class="w"> </span><span class="nc">NVARCHAR</span><span class="p">(</span><span class="mi">100</span><span class="p">)</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">HrInicio</span><span class="w"> </span><span class="nc">TIME</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"> </span><span class="cm">/* Startint block time */</span><span class="w"></span> +<span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="nc">TIME</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"> </span><span class="cm">/* Ending block time */</span><span class="w"></span> +<span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="nc">INT</span><span class="w"> </span><span class="k">DEFAULT</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="cm">/* 0 = unblocked, 1 = blocked */</span><span class="w"></span> +<span class="w"> </span><span class="k">PRIMARY</span><span class="w"> </span><span class="k">KEY</span><span class="w"> </span><span class="p">(</span><span class="n">Id</span><span class="p">)</span><span class="w"></span> +<span class="p">);</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> + +<span class="cm">/* Don&#39;t block the SA user, precautions, you know */</span><span class="w"></span> +<span class="k">ALTER</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"></span> +<span class="w"> </span><span class="k">ADD</span><span class="w"> </span><span class="k">CONSTRAINT</span><span class="w"> </span><span class="n">chk_users</span><span class="w"> </span><span class="k">CHECK</span><span class="w"> </span><span class="p">(</span><span class="n">LoginName</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;sa&#39;</span><span class="p">));</span><span class="w"></span> + +<span class="k">ALTER</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"></span> +<span class="w"> </span><span class="k">ADD</span><span class="w"> </span><span class="k">CONSTRAINT</span><span class="w"> </span><span class="n">chk_hora_final_maior</span><span class="w"> </span><span class="k">CHECK</span><span class="w"> </span><span class="p">(</span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="n">HrInicio</span><span class="p">);</span><span class="w"></span> + +<span class="k">ALTER</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"></span> +<span class="w"> </span><span class="k">ADD</span><span class="w"> </span><span class="k">CONSTRAINT</span><span class="w"> </span><span class="n">chk_status_bloqueio</span><span class="w"> </span><span class="k">CHECK</span><span class="w"> </span><span class="p">(</span><span class="n">Bloqueado</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">));</span><span class="w"></span> + +<span class="k">CREATE</span><span class="w"> </span><span class="k">SEQUENCE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">seq_HorariosBloqueio</span><span class="w"> </span><span class="k">START</span><span class="w"> </span><span class="k">WITH</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="n">INCREMENT</span><span class="w"> </span><span class="k">BY</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +</code></pre></div> + +<p>After creating the table, let's check the procedure that will handle the enabling/disabling the users. Be aware that on the procedure, I've set the database name where the table was stored, you can change it replacing the <code>DBATOOLS</code> text to the database name where you created the table.</p> +<div class="highlight"><pre><span></span><code><span class="k">IF</span><span class="w"> </span><span class="nf">OBJECT_ID</span><span class="p">(</span><span class="s1">&#39;dbo.sp_ValidarLogin&#39;</span><span class="p">)</span><span class="w"> </span><span class="k">IS</span><span class="w"> </span><span class="k">NULL</span><span class="w"></span> +<span class="w"> </span><span class="k">EXEC</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;CREATE PROCEDURE dbo.sp_ValidarLogin AS RETURN 0;&#39;</span><span class="p">);</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> + +<span class="k">CREATE</span><span class="w"> </span><span class="ow">OR</span><span class="w"> </span><span class="k">ALTER</span><span class="w"> </span><span class="k">PROC</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">sp_ValidarLogin</span><span class="w"></span> +<span class="k">AS</span><span class="w"> </span><span class="k">BEGIN</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="nc">NVARCHAR</span><span class="p">(</span><span class="mi">100</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="nc">TIME</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="k">SET</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nf">CAST</span><span class="p">(</span><span class="nf">GETDATE</span><span class="p">()</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="nc">TIME</span><span class="p">);</span><span class="w"></span> + +<span class="w"> </span><span class="cm">/* Block the ones that aren&#39;t blocked already and maches the time */</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="n">block_cursor</span><span class="w"> </span><span class="nc">CURSOR</span><span class="w"></span> +<span class="w"> </span><span class="k">FOR</span><span class="w"> </span><span class="k">SELECT</span><span class="w"> </span><span class="n">LoginName</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&lt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&gt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"></span> +<span class="w"> </span><span class="k">OPEN</span><span class="w"> </span><span class="n">block_cursor</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">block_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> + +<span class="w"> </span><span class="k">WHILE</span><span class="w"> </span><span class="nb">@@FETCH_STATUS</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"></span> +<span class="w"> </span><span class="k">BEGIN</span><span class="w"></span> +<span class="w"> </span><span class="k">exec</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;ALTER LOGIN &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="s1">&#39; DISABLE;&#39;</span><span class="p">);</span><span class="w"></span> + +<span class="w"> </span><span class="k">print</span><span class="w"> </span><span class="s1">&#39;Bloqued usuario &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">block_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> +<span class="w"> </span><span class="k">END</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">CLOSE</span><span class="w"> </span><span class="n">block_cursor</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="k">DEALLOCATE</span><span class="w"> </span><span class="n">block_cursor</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">UPDATE</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">SET</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&lt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&gt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"></span> + + +<span class="w"> </span><span class="cm">/* Enable up who was blocked */</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="nc">CURSOR</span><span class="w"></span> +<span class="w"> </span><span class="k">FOR</span><span class="w"> </span><span class="k">SELECT</span><span class="w"> </span><span class="n">LoginName</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="p">(</span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">OR</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="p">)</span><span class="w"></span> +<span class="w"> </span><span class="k">OPEN</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> + +<span class="w"> </span><span class="k">WHILE</span><span class="w"> </span><span class="nb">@@FETCH_STATUS</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"></span> +<span class="w"> </span><span class="k">BEGIN</span><span class="w"></span> +<span class="w"> </span><span class="k">exec</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;ALTER LOGIN &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"> </span><span class="o">+</span><span class="s1">&#39; ENABLE;&#39;</span><span class="p">);</span><span class="w"></span> + +<span class="w"> </span><span class="k">print</span><span class="w"> </span><span class="s1">&#39;Unbloqued usuario &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> +<span class="w"> </span><span class="k">END</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">CLOSE</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="k">DEALLOCATE</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">UPDATE</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">SET</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="p">(</span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">OR</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="p">)</span><span class="w"></span> +<span class="k">END</span><span class="p">;</span><span class="w"></span> +</code></pre></div> + +<p>Ok, so now all you have to do, is schedule a job to run that stored procedure from minute to minute. Again, the main idea is tell the procedure when a user must be blocked and when it'll be unblocked. </p> +<div class="highlight"><pre><span></span><code><span class="err"> -- Will block the user protheus from 10 AM till 15 PM</span> +<span class="err"> INSERT INTO dbo.HorariosBloqueio (Id, LoginName, HrInicio, HrTermino) VALUES (NEXT VALUE FOR seq_HorariosBloqueio, &#39;protheus&#39;, &#39;10:00:00&#39;, &#39;15:00:00&#39;);</span> +</code></pre></div>Removing a user from SQL Server database who owns a schema2019-09-06T07:00:00-03:002020-10-21T18:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2019-09-06:/en/removing-user-from-sql-server-database.html<p>Your customer urge you to drop a user from the MsSQL Server database, but you stuck with the following related error:</p> +<div class="highlight"><pre><span></span><code><span class="n">Error</span><span class="o">:</span> <span class="mi">15138</span> <span class="n">The</span> <span class="n">database</span> <span class="n">principal</span> <span class="n">owns</span> <span class="n">a</span> <span class="n">schema</span> <span class="k">in</span> <span class="n">the</span> <span class="n">database</span><span class="o">,</span> <span class="n">and</span> <span class="n">cannot</span> <span class="n">be</span> <span class="n">dropped</span><span class="o">.</span> +</code></pre></div> + +<p>That means that the user owns one or more shcemas of your database. If …</p><p>Your customer urge you to drop a user from the MsSQL Server database, but you stuck with the following related error:</p> +<div class="highlight"><pre><span></span><code><span class="n">Error</span><span class="o">:</span> <span class="mi">15138</span> <span class="n">The</span> <span class="n">database</span> <span class="n">principal</span> <span class="n">owns</span> <span class="n">a</span> <span class="n">schema</span> <span class="k">in</span> <span class="n">the</span> <span class="n">database</span><span class="o">,</span> <span class="n">and</span> <span class="n">cannot</span> <span class="n">be</span> <span class="n">dropped</span><span class="o">.</span> +</code></pre></div> + +<p>That means that the user owns one or more shcemas of your database. If you don't have access to the SSMS to see which schema or objects the user owns, the following SQL should do the job.</p> +<div class="highlight"><pre><span></span><code><span class="k">USE</span><span class="w"> </span><span class="o">[</span><span class="n">DATABASENAME</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> + +<span class="k">select</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Objeto</span><span class="p">,</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Owner</span><span class="w"></span> +<span class="k">from</span><span class="w"> </span><span class="n">sys</span><span class="p">.</span><span class="n">schemas</span><span class="w"> </span><span class="n">so</span><span class="w"></span> +<span class="k">inner</span><span class="w"> </span><span class="k">join</span><span class="w"> </span><span class="n">sysusers</span><span class="w"> </span><span class="n">su</span><span class="w"> </span><span class="k">on</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">principal_id</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">uid</span><span class="w"></span> +<span class="k">where</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">&#39;username&#39;</span><span class="w"></span> + +<span class="k">select</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Objeto</span><span class="p">,</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Owner</span><span class="p">,</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">xtype</span><span class="w"> </span><span class="n">Tipo</span><span class="w"></span> +<span class="k">from</span><span class="w"> </span><span class="n">sys</span><span class="p">.</span><span class="n">sysobjects</span><span class="w"> </span><span class="n">so</span><span class="w"></span> +<span class="k">inner</span><span class="w"> </span><span class="k">join</span><span class="w"> </span><span class="n">sysusers</span><span class="w"> </span><span class="n">su</span><span class="w"> </span><span class="k">on</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">uid</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">uid</span><span class="w"></span> +<span class="k">where</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">&#39;username&#39;</span><span class="w"></span> +</code></pre></div> + +<p>Once you have the objects/schemas owned by the user, you can change them with the following SQL (schema change sample):</p> +<div class="highlight"><pre><span></span><code><span class="k">USE</span><span class="w"> </span><span class="o">[</span><span class="n">DATABASENAME</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +<span class="k">ALTER</span><span class="w"> </span><span class="k">AUTHORIZATION</span><span class="w"> </span><span class="k">ON</span><span class="w"> </span><span class="k">SCHEMA</span><span class="o">::[</span><span class="n">db_datareader</span><span class="o">]</span><span class="w"> </span><span class="k">TO</span><span class="w"> </span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="w"> </span><span class="c1">-- new owner username</span> +<span class="k">ALTER</span><span class="w"> </span><span class="k">AUTHORIZATION</span><span class="w"> </span><span class="k">ON</span><span class="w"> </span><span class="k">SCHEMA</span><span class="o">::[</span><span class="n">db_datawriter</span><span class="o">]</span><span class="w"> </span><span class="k">TO</span><span class="w"> </span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +</code></pre></div> + +<p>Then you're ready to drop the user <code>DROP USER [username]</code></p> +<h2>How to list all the schemas and it's owners?</h2> +<p>Here's a script to list schemas and it's owners.</p> +<div class="highlight"><pre><span></span><code><span class="k">USE</span><span class="w"> </span><span class="o">[</span><span class="n">DATABASENAME</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +<span class="k">SELECT</span><span class="w"></span> +<span class="w"> </span><span class="nf">schema_name</span><span class="p">(</span><span class="nf">schema_id</span><span class="p">)</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="n">schemaname</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="nf">user_name</span><span class="p">(</span><span class="n">schm</span><span class="p">.</span><span class="n">principal_id</span><span class="p">)</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="n">username</span><span class="p">,</span><span class="w"> </span><span class="o">*</span><span class="w"></span> +<span class="k">FROM</span><span class="w"> </span><span class="n">sys</span><span class="p">.</span><span class="n">schemas</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="n">schm</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +</code></pre></div>Limiting Connection Resources on SQL Server2019-08-12T12:00:00-03:002019-08-12T12:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2019-08-12:/en/limiting-connection-resources-sql-server.html<p>Have you ever suffered from a slow SQLServer database? Someone love to run that heavy query in the database? Resource Governor to the rescue. You can set a few rules on how users (connections actually) will use the server/database resources based on a few things.</p> +<p>First things first, if …</p><p>Have you ever suffered from a slow SQLServer database? Someone love to run that heavy query in the database? Resource Governor to the rescue. You can set a few rules on how users (connections actually) will use the server/database resources based on a few things.</p> +<p>First things first, if you don't have DAC enabled, enable it now. Dealing with resource governor can lock you out of the database and leave you without action (almost... you can start the server with -c -m -f).</p> +<p>Now to understand how Resource Governor works, we have a few keywords <code>resource pool</code>, <code>workload group</code> e <code>Classifier Function</code>.</p> +<p><img alt="Pool Sample" src="/images/sql-pool.png"></p> +<h2>Resource Pool</h2> +<p>First, we have the Resource Pool, with is the bigger resource group that we have the ability to manage. With it, we can set a few things like: <code>MIN_CPU_PERCENT</code>, <code>MAX_CPU_PERCENT</code>, <code>MIN_MEMORY_PERCENT</code>, <code>MAX_MEMORY_PERCENT</code>, <code>MIN_IOPS_PER_VOLUME</code>, and <code>MAX_IOPS_PER_VOLUME</code>.</p> +<p>Be aware that the <code>MAX_CPU_PERCENT</code> will just "works" when there is another connection with a higher priority, otherwise it will use what is available. Let's create a pool.</p> +<div class="highlight"><pre><span></span><code><span class="k">CREATE</span><span class="w"> </span><span class="n">RESOURCE</span><span class="w"> </span><span class="n">POOL</span><span class="w"> </span><span class="o">[</span><span class="n">SpreadSheet</span><span class="o">]</span><span class="w"></span> +<span class="k">WITH</span><span class="w"> </span><span class="p">(</span><span class="w"></span> +<span class="w"> </span><span class="n">MIN_CPU_PERCENT</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">MAX_CPU_PERCENT</span><span class="o">=</span><span class="mi">20</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">MIN_MEMORY_PERCENT</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">MAX_MEMORY_PERCENT</span><span class="o">=</span><span class="mi">20</span><span class="w"></span> +<span class="p">);</span><span class="w"></span> +</code></pre></div> + +<p>## Workload Group</p> +<p>Then we have a workload group that "works" inside a pool, so you can have another granularity on how you can split your resources. Again, we have a few options: <code>IMPORTANCE</code>, <code>REQUEST_MAX_CPU_TIME_SEC</code>, <code>REQUEST_MAX_MEMORY_GRANT_PERCENT</code>, <code>GROUP_MAX_REQUESTS</code>.</p> +<p>The <code>IMPORTANCE</code> set guesses what... the importance of that workload inside the pool, you can set LOW, MEDIUM, HIGH. GROUP_MAX_REQUESTS sets how many requests can run at the same time inside that workload (0 will set as NO LIMIT)</p> +<div class="highlight"><pre><span></span><code><span class="k">CREATE</span><span class="w"> </span><span class="n">WORKLOAD</span><span class="w"> </span><span class="k">GROUP</span><span class="w"> </span><span class="o">[</span><span class="n">DepartmentA</span><span class="o">]</span><span class="w"> </span> +<span class="k">WITH</span><span class="w"> </span><span class="p">(</span><span class="w"></span> +<span class="w"> </span><span class="n">GROUP_MAX_REQUESTS</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">IMPORTANCE</span><span class="o">=</span><span class="n">LOW</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">REQUEST_MAX_CPU_TIME_SEC</span><span class="o">=</span><span class="mi">10</span><span class="p">,</span><span class="w"> </span><span class="c1">-- Time running/using CPU</span> +<span class="w"> </span><span class="n">REQUEST_MAX_MEMORY_GRANT_PERCENT</span><span class="o">=</span><span class="mi">15</span><span class="w"></span> +<span class="p">)</span><span class="w"> </span><span class="k">USING</span><span class="w"> </span><span class="o">[</span><span class="n">SpreadSheet</span><span class="o">]</span><span class="p">;</span><span class="w"> </span><span class="c1">-- pool name here</span> +</code></pre></div> + +<h2>Classifier Function</h2> +<p>This is where everything begins... This is the entry point where you should set the group name. It's a function that will run for every new connection so be aware that if your function runs lots of queries or some heavy stuff... that time will be added to the connection handshake. If the function returns NULL or a group name that doesn't exist, the 'default' group will be used... Yes, there is a default workload group where everything runs where there's no classifier.</p> +<div class="highlight"><pre><span></span><code><span class="k">CREATE</span><span class="w"> </span><span class="k">FUNCTION</span><span class="w"> </span><span class="n">fnClassWorkloadGovernor</span><span class="p">()</span><span class="w"> </span> +<span class="k">RETURNS</span><span class="w"> </span><span class="n">SYSNAME</span><span class="w"> </span><span class="k">WITH</span><span class="w"> </span><span class="n">SCHEMABINDING</span><span class="w"> </span> +<span class="k">AS</span><span class="w"> </span> +<span class="k">BEGIN</span><span class="w"> </span> +<span class="w"> </span><span class="k">IF</span><span class="w"> </span><span class="nf">APP_NAME</span><span class="p">()</span><span class="w"> </span><span class="ow">LIKE</span><span class="w"> </span><span class="s1">&#39;%Excel%&#39;</span><span class="w"></span> +<span class="w"> </span><span class="k">RETURN</span><span class="w"> </span><span class="s1">&#39;DepartmentA&#39;</span><span class="w"></span> + +<span class="w"> </span><span class="k">IF</span><span class="w"> </span><span class="nf">HOST_NAME</span><span class="p">()</span><span class="w"> </span><span class="ow">LIKE</span><span class="w"> </span><span class="s1">&#39;%THAT_MACHINE_OR_APP_SERVER%&#39;</span><span class="w"></span> +<span class="w"> </span><span class="k">RETURN</span><span class="w"> </span><span class="s1">&#39;LowPriority&#39;</span><span class="w"></span> + +<span class="w"> </span><span class="k">RETURN</span><span class="w"> </span><span class="k">NULL</span><span class="w"></span> +<span class="k">END</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> + +<span class="k">ALTER</span><span class="w"> </span><span class="n">RESOURCE</span><span class="w"> </span><span class="n">GOVERNOR</span><span class="w"> </span><span class="k">WITH</span><span class="w"> </span><span class="p">(</span><span class="n">CLASSIFIER_FUNCTION</span><span class="o">=</span><span class="n">dbo</span><span class="p">.</span><span class="n">fnClassWorkloadGovernor</span><span class="p">);</span><span class="w"></span> +<span class="k">ALTER</span><span class="w"> </span><span class="n">RESOURCE</span><span class="w"> </span><span class="n">GOVERNOR</span><span class="w"> </span><span class="k">RECONFIGURE</span><span class="p">;</span><span class="w"></span> +</code></pre></div> + +<p>There you go... now you have a fully working resource governor, but look out that If you want to delete that classifier function, first you have to remove it from the resource governor (look the SCHEMABINDING at the create up there).</p> +<p>To disable Resource Governor</p> +<div class="highlight"><pre><span></span><code><span class="k">ALTER</span><span class="w"> </span><span class="n">RESOURCE</span><span class="w"> </span><span class="n">GOVERNOR</span><span class="w"> </span><span class="k">WITH</span><span class="w"> </span><span class="p">(</span><span class="n">CLASSIFIER_FUNCTION</span><span class="o">=</span><span class="k">null</span><span class="p">)</span><span class="w"></span> +<span class="k">ALTER</span><span class="w"> </span><span class="n">RESOURCE</span><span class="w"> </span><span class="n">GOVERNOR</span><span class="w"> </span><span class="k">RECONFIGURE</span><span class="w"></span> + +<span class="k">ALTER</span><span class="w"> </span><span class="n">RESOURCE</span><span class="w"> </span><span class="n">GOVERNOR</span><span class="w"> </span><span class="n">DISABLE</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +</code></pre></div> \ No newline at end of file diff --git a/en/feeds/sql-server.atom.xml.gz b/en/feeds/sql-server.atom.xml.gz new file mode 100644 index 000000000..1101825fc Binary files /dev/null and b/en/feeds/sql-server.atom.xml.gz differ diff --git a/en/feeds/tools.atom.xml b/en/feeds/tools.atom.xml new file mode 100644 index 000000000..634a2bbee --- /dev/null +++ b/en/feeds/tools.atom.xml @@ -0,0 +1,10 @@ + +Sipmann - Toolshttps://www.sipmann.com/en/2020-12-02T14:00:00-03:00Apache Nifi JSON to SQL Replacing underscore2020-12-02T14:00:00-03:002020-12-02T14:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-12-02:/en/apache-nifi-json-to-sql-replacing-underscore.html<p>Recently I was doing some ETL with Apache NiFi. But after a few minutes of drawing my flow, I saw that the component ConvertJSONToSQL was replacing the underscore ('_') from the field name in the where condition (I was preparing an Update SQL). That was weird because, at the set …</p><p>Recently I was doing some ETL with Apache NiFi. But after a few minutes of drawing my flow, I saw that the component ConvertJSONToSQL was replacing the underscore ('_') from the field name in the where condition (I was preparing an Update SQL). That was weird because, at the set statement, the field name was kept intact. After some research, I found that the property (see bellow) <code>Translate Field Names</code> was responsible for that weird replacement.</p> +<p><img alt="Apache NiFi JSONToSQL config" src="/images/apache_nifi_jsontosql.png"></p> +<p>Before setting it to <strong>FALSE</strong>, be aware that the properties on your JSON data must match exactly the name of your fields.</p>Using git hooks to easy your life2019-07-30T20:00:00-03:002019-07-30T20:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2019-07-30:/en/using_git_hooks_easy_your_life.html<p>Hey folks, it's been a time since my last post. In the meantime, I moved to another state, changed job, and started learning new kinds of stuff. Today I would like to share one thing that I usually do with my small git projects. Git has many cool features, git …</p><p>Hey folks, it's been a time since my last post. In the meantime, I moved to another state, changed job, and started learning new kinds of stuff. Today I would like to share one thing that I usually do with my small git projects. Git has many cool features, git hooks were one of them. I'll talk about the pre-commit hook today.</p> +<p>Let's say that, for some reason, you don't have a CI tool/server running after every commit and you want to enforce that every developer runs the tests before every commit? Git pre-commit to the rescue. You can code the hooks with shell, ruby, python, and I could be wrong, but even PHP would work. pre-commit is a client-side hook (we have server side too) and he's located inside the <cite>.git/hooks</cite> folder. Let's jump to the code... Create a file called 'pre-commit' inside that folder with the following code.</p> +<div class="highlight"><pre><span></span><span class="ch">#!/bin/bash</span> +npm <span class="nb">test</span> <span class="c1"># assuming you&#39;re using it inside a nodeJS project</span> +</pre></div> +<p>Don't forget to make the script executable!! Now break your test and try to commit. That's easy but can save you from breaking the tests at the main CI/Travis/Codeship/etc and being notified by email :). Why not even validate the lint of your project or check if the coverage doesn't fall? Does your team/company have a patter for commit messages? No problem, there is a hook called <cite>commit-msg</cite> that you can use to validate your message.</p> + \ No newline at end of file diff --git a/en/feeds/tools.atom.xml.gz b/en/feeds/tools.atom.xml.gz new file mode 100644 index 000000000..996f872f0 Binary files /dev/null and b/en/feeds/tools.atom.xml.gz differ diff --git a/en/flutter_with_firebase_auth_crashing.html b/en/flutter_with_firebase_auth_crashing.html new file mode 100644 index 000000000..f3dfa3d29 --- /dev/null +++ b/en/flutter_with_firebase_auth_crashing.html @@ -0,0 +1,434 @@ + + + + + + + + Flutter + firebase auth crashing - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Flutter + firebase auth crashing

+
+ +
+
+ +
+

Hey Folks, recently I've started learning Flutter and right after a TODO List, I tried a Firebase integration. But as soon as I started setting the dependencies, my app stopped opening... just a crash. After a few logs digging, I've found the following log.

+
AndroidRuntime: FATAL EXCEPTION: main
+AndroidRuntime: Process: com.example.diadocasal, PID: 13672
+AndroidRuntime: java.lang.NoClassDefFoundError: Failed resolution of: Landroid/support/v4/util/ArrayMap;
+AndroidRuntime:     at com.google.android.gms.internal.measurement.zzca.<clinit>(Unknown Source:60)
+AndroidRuntime:     at com.google.android.gms.internal.measurement.zzcm.zzr(Unknown Source:7)
+AndroidRuntime:     at com.google.android.gms.measurement.internal.zzfj.<init>(Unknown Source:23)
+
+ +

Notice the "NoClassDefFound" of an ArrayMap. To solve that I did the following changes to the files:

+
//build.gradle file
+ ext.kotlin_version = '1.3.20'
+[...]
+ dependencies {
+        classpath 'com.android.tools.build:gradle:3.3.0' // gradle version
+
+ +
;gradle.properties file
+org.gradle.jvmargs=-Xmx1536M ;mine have just this line at first
+android.useAndroidX=true ; uses androidX instead of the default support library
+android.enableJetifier=true ; uses jetpack libraries
+android.enableR8=true ; the new code shriker
+
+ +

After that, voilà, app up and running.

+
+ + +
+
+

Translations:

+
    +
+
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/flutter_with_firebase_auth_crashing.html.gz b/en/flutter_with_firebase_auth_crashing.html.gz new file mode 100644 index 000000000..f0e35616f Binary files /dev/null and b/en/flutter_with_firebase_auth_crashing.html.gz differ diff --git a/en/index.html b/en/index.html new file mode 100644 index 000000000..294078b0a --- /dev/null +++ b/en/index.html @@ -0,0 +1,603 @@ + + + + + + + + Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+ +
+
+
+

Apache Nifi JSON to SQL Replacing underscore

+
+ +
+
+ +
+

Recently I was doing some ETL with Apache NiFi. But after a few minutes of drawing my flow, I saw that the component ConvertJSONToSQL was replacing the underscore ('_') from the field name in the where condition (I was preparing an Update SQL). That was weird because, at the set …

+
+ + + +
+
+
+
+ +
+
+ + + + + + + +
+

So, you use Entity Framework Core, and you usually code your selects like the following, maybe you are getting too much data.

+
var products = Products
+    .Where(p => p.UnitsInStock > 0)
+    .OrderBy(p => p.ProductName)
+    .ToList()
+
+ +

Running the query above, on my table, you'll get the following output, take a look …

+
+ + + +
+
+
+
+
+ + + + + +
+

Zabbix Running on Low Memory Mode

+
+ +
+
+ +
+

Hey folks, another Zabbix post today. This one it's about increasing the Zabbix Server Cache. It's pretty common (if you have the default settings only) get a warning about your Zabbix value cache running on low memory mode at your dashboard or logs.

+

Zabbix Dashboard warning about the memory problem +Zabbix Dashboard cache graph 70% used

+

To solve, go back to your Zabbix …

+
+ + + +
+
+
+
+
+ + + + + + + +
+

I've been migration some bash scripts that I have to PowerShell, and it's time to migrate a script that monitors the replication of a MySQL database. The credit for the original script goes to Paweł. It's a simple script where I seek a few tags/fields that we get from …

+
+ + + +
+
+
+
+
+
+

Microsoft Against Covid

+
+ +
+
+ +
+

Has your job been affected by covid? Well, last week I've posted on Grepora about a Free Certification Voucher that Microsoft was giving away at the Microsoft Ignite event. After that, I found that they were also giving a huge discount to people who have had their job affected by …

+
+ + + +
+
+
+
+
+ + + + + +
+

The power of PowerShell

+
+ +
+
+ +
+

As a long time Linux user, I've automated a few things with bash scripts and stayed away from PowerShell... I've moved to a Windows environment a few years ago and still, haven gave a shot to PS. But why not? I've made a few scripts to automate some tasks at …

+
+ + + +
+
+
+
+
+ + + + + +
+

Top Level Statement in C# 9

+
+ +
+
+ +
+

Hey folks, I'm coming along to tell you a few things about the new feature of C# 9. Every time you want to start a new project, you always have the same Main File, with the same structure. At the next version of C# (version 9), we'll have a new …

+
+ + + +
+
+
+
+
+ + 1 + 2 + 3 + » + +
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/index.html.gz b/en/index.html.gz new file mode 100644 index 000000000..c7b6e1e04 Binary files /dev/null and b/en/index.html.gz differ diff --git a/en/index2.html b/en/index2.html new file mode 100644 index 000000000..f6e02655f --- /dev/null +++ b/en/index2.html @@ -0,0 +1,582 @@ + + + + + + + + Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Zabbix poller processes more than 75%

+
+ +
+
+ +
+

Hey folks, this is the third post about tweaking the Zabbix configurations. All changes that I've suggested here were based on a Zabbix Server with 50+ hosts. Another thing that can happen to your server, it's the poller get overwhelmed by the amount of servers that need to be polled …

+
+ + + +
+
+
+
+
+ + + + + + + +
+

Sometimes you get your self in need to monitor a website's health or it's content for changes. Of course, there's plenty of options out there, but for the sake of curiosity, let's code our own to see what we can do. First things first. Everything you'll see here, you can …

+
+ + + +
+
+
+
+
+ + + + + + + +
+

Hey folks, if you want to achieve some certification this year, keep an eye open for vouchers. A few months ago, Oracle released a set of free courses with certifications. Now it's Microsoft time. Microsoft is updating they're certifications and we have a voucher of 80% discount using the coupon …

+
+ + + +
+
+
+
+
+
+

Zabbix ICMP pinger processes more than 75%

+
+ +
+
+ +
+

So your monitoring sytems have grown and your zabbix started loggin "Zabbix icmp pinger processes more than 75% busy" at the dashboard.

+

Dashboard do zabbix avisando sobre o erro

+

All you have to do is open your config file (/etc/zabbix/zabbix_server.conf) and find the a tag named StartPingers. It'll be commented by default. Uncomment it …

+
+ + + +
+
+
+
+
+
+

Zabbix Server Out of Memory

+
+ +
+
+ +
+

Do you have a crashing Zabbix Server and looking through the log /var/log/zabbix/zabbix_server.log you see the following out of memory message?

+
__mem_malloc: skipped 0 asked 24 skip_min 18446744073709551615 skip_max 0
+[file:dbconfig.c,line:94] __zbx_mem_realloc(): out of memory (requested 16 bytes)
+[file:dbconfig.c,line …

+
+ + + +
+
+
+
+
+
+

Flutter + firebase auth crashing

+
+ +
+
+ +
+

Hey Folks, recently I've started learning Flutter and right after a TODO List, I tried a Firebase integration. But as soon as I started setting the dependencies, my app stopped opening... just a crash. After a few logs digging, I've found the following log.

+
AndroidRuntime: FATAL EXCEPTION: main
+AndroidRuntime: Process …

+
+ + + +
+
+
+
+
+ + +
+

Your customer urge you to drop a user from the MsSQL Server database, but you stuck with the following related error:

+
Error: 15138 The database principal owns a schema in the database, and cannot be dropped.
+
+ +

That means that the user owns one or more shcemas of your database. If …

+
+ + + +
+
+
+
+
+ + + + + +
+

Limiting Connection Resources on SQL Server

+
+ +
+
+ +
+

Have you ever suffered from a slow SQLServer database? Someone love to run that heavy query in the database? Resource Governor to the rescue. You can set a few rules on how users (connections actually) will use the server/database resources based on a few things.

+

First things first, if …

+
+ + + +
+
+
+
+
+
+

Using git hooks to easy your life

+
+ +
+
+ +
+

Hey folks, it's been a time since my last post. In the meantime, I moved to another state, changed job, and started learning new kinds of stuff. Today I would like to share one thing that I usually do with my small git projects. Git has many cool features, git …

+
+ + + +
+
+
+
+ +
+
+ « + + 1 + 2 + 3 + » + +
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/index2.html.gz b/en/index2.html.gz new file mode 100644 index 000000000..642adebb4 Binary files /dev/null and b/en/index2.html.gz differ diff --git a/en/index3.html b/en/index3.html new file mode 100644 index 000000000..113b3bd78 --- /dev/null +++ b/en/index3.html @@ -0,0 +1,526 @@ + + + + + + + + Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+ + + + + + + +
+

This is the first part of a microservices development series. The service will consist of the bellow architecture, where we will expose an image optimizer service that will forward the request to a RabbitMQ queue and answer with the bytecode of the optimized image. It shouldn't be a long series …

+
+ + + +
+
+
+
+
+
+

Connecting to a database through SSH

+
+ +
+
+ +
+

If someday, for some reason, you need to establish a connection with a database which is behind a firewall and you only have SSH access on that server (and you don't want to use a CLI) you can do an SSH tunnel. It's pretty simple, bellow has a sample of …

+
+ + + +
+
+
+
+
+
+

Now posting on Grepora

+
+ +
+
+ +
+

A few weeks ago I started posting at Grepora blog. If you like or are looking for some Oracle related stuff, Grepora it's a good place to go and spend a time reading :). From time to time I'll be posting there, it doesn't mean that this blog will be closed …

+
+ + + +
+
+
+
+
+ + + + + + + +
+

Since Parcel JS arrived, I've been using it a lot as an awesome alternative for WebPack. Webpack isn't bad but IMO it's too complex for the job and parcel do the same (at least the basic) with almost zero configuration. But if you need to create many apps (like a …

+
+ + + +
+
+
+
+
+ + + + + + + +
+

Last day I decided to deploy a MySQL Docker image to work with my Java application. I've been using PostgreSQL instead and have no problems at all, but after I moved to MySQL, the app didn't connect anymore with the database and throw some "Could not open connection" at my …

+
+ + + +
+
+
+
+ +
+
+ + + + + +
+

Change display settings on linux with Disper

+
+ +
+
+ +
+

From time to time, I change the Linux distro on my laptop or just do a fresh install on it. And once in a while, have random problems with external displays. It can be something really "simple" like don't detecting the external monitor or something crazy like the image below …

+
+ + + +
+
+
+
+
+
+

Java - Files.readAllBytes throws OutOfMemory

+
+ +
+
+ +
+

When you need to interact with files, there's the possibility to read all bytes from the file with Files.readAllBytes. But be aware of the kinds of files your application will deal with because the Java API files have a limit for the buffer that is defined as Integer.MAX_VALUE …

+
+ + + +
+
+
+
+
+ « + + 1 + 2 + 3 + +
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/index3.html.gz b/en/index3.html.gz new file mode 100644 index 000000000..3fffebaeb Binary files /dev/null and b/en/index3.html.gz differ diff --git a/en/limiting-connection-resources-sql-server.html b/en/limiting-connection-resources-sql-server.html new file mode 100644 index 000000000..ae88e23dc --- /dev/null +++ b/en/limiting-connection-resources-sql-server.html @@ -0,0 +1,533 @@ + + + + + + + + Limiting Connection Resources on SQL Server - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Limiting Connection Resources on SQL Server

+
+ +
+
+ +
+

Have you ever suffered from a slow SQLServer database? Someone love to run that heavy query in the database? Resource Governor to the rescue. You can set a few rules on how users (connections actually) will use the server/database resources based on a few things.

+

First things first, if you don't have DAC enabled, enable it now. Dealing with resource governor can lock you out of the database and leave you without action (almost... you can start the server with -c -m -f).

+

Now to understand how Resource Governor works, we have a few keywords resource pool, workload group e Classifier Function.

+

Pool Sample

+

Resource Pool

+

First, we have the Resource Pool, with is the bigger resource group that we have the ability to manage. With it, we can set a few things like: MIN_CPU_PERCENT, MAX_CPU_PERCENT, MIN_MEMORY_PERCENT, MAX_MEMORY_PERCENT, MIN_IOPS_PER_VOLUME, and MAX_IOPS_PER_VOLUME.

+

Be aware that the MAX_CPU_PERCENT will just "works" when there is another connection with a higher priority, otherwise it will use what is available. Let's create a pool.

+
CREATE RESOURCE POOL [SpreadSheet]
+WITH (
+    MIN_CPU_PERCENT=0,
+    MAX_CPU_PERCENT=20,
+    MIN_MEMORY_PERCENT=0,
+    MAX_MEMORY_PERCENT=20
+);
+
+ +

## Workload Group

+

Then we have a workload group that "works" inside a pool, so you can have another granularity on how you can split your resources. Again, we have a few options: IMPORTANCE, REQUEST_MAX_CPU_TIME_SEC, REQUEST_MAX_MEMORY_GRANT_PERCENT, GROUP_MAX_REQUESTS.

+

The IMPORTANCE set guesses what... the importance of that workload inside the pool, you can set LOW, MEDIUM, HIGH. GROUP_MAX_REQUESTS sets how many requests can run at the same time inside that workload (0 will set as NO LIMIT)

+
CREATE WORKLOAD GROUP [DepartmentA] 
+WITH (
+    GROUP_MAX_REQUESTS=2,
+    IMPORTANCE=LOW,
+    REQUEST_MAX_CPU_TIME_SEC=10, -- Time running/using CPU
+    REQUEST_MAX_MEMORY_GRANT_PERCENT=15
+) USING [SpreadSheet]; -- pool name here
+
+ +

Classifier Function

+

This is where everything begins... This is the entry point where you should set the group name. It's a function that will run for every new connection so be aware that if your function runs lots of queries or some heavy stuff... that time will be added to the connection handshake. If the function returns NULL or a group name that doesn't exist, the 'default' group will be used... Yes, there is a default workload group where everything runs where there's no classifier.

+
CREATE FUNCTION fnClassWorkloadGovernor() 
+RETURNS SYSNAME WITH SCHEMABINDING 
+AS 
+BEGIN 
+    IF APP_NAME() LIKE '%Excel%'
+        RETURN 'DepartmentA'
+
+    IF HOST_NAME() LIKE '%THAT_MACHINE_OR_APP_SERVER%'
+        RETURN 'LowPriority'
+
+    RETURN NULL
+END
+GO
+
+ALTER RESOURCE GOVERNOR WITH (CLASSIFIER_FUNCTION=dbo.fnClassWorkloadGovernor);
+ALTER RESOURCE GOVERNOR RECONFIGURE;
+
+ +

There you go... now you have a fully working resource governor, but look out that If you want to delete that classifier function, first you have to remove it from the resource governor (look the SCHEMABINDING at the create up there).

+

To disable Resource Governor

+
ALTER RESOURCE GOVERNOR WITH (CLASSIFIER_FUNCTION=null)
+ALTER RESOURCE GOVERNOR RECONFIGURE
+
+ALTER RESOURCE GOVERNOR DISABLE
+GO
+

+
+ + +
+
+

Translations:

+
    +
+
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/limiting-connection-resources-sql-server.html.gz b/en/limiting-connection-resources-sql-server.html.gz new file mode 100644 index 000000000..a4d377bcf Binary files /dev/null and b/en/limiting-connection-resources-sql-server.html.gz differ diff --git a/en/linux-external-display-with-disper.html b/en/linux-external-display-with-disper.html new file mode 100644 index 000000000..22e0990be --- /dev/null +++ b/en/linux-external-display-with-disper.html @@ -0,0 +1,421 @@ + + + + + + + + Change display settings on linux with Disper - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Change display settings on linux with Disper

+
+ +
+
+ +
+

From time to time, I change the Linux distro on my laptop or just do a fresh install on it. And once in a while, have random problems with external displays. It can be something really "simple" like don't detecting the external monitor or something crazy like the image below.

+Display bug +

As you can see at the image, the mint detected the display but mirrored it in a crazy way that works but doesn't at the same time. If you try anything and doesn't get working, or just wanna skip the whole job of configuring complexes text files, give a try to Disper. Download the latest version. +Extract it on any folder, and make install it (on the extracted folder).

+
make install
+
+

After that, you can start using it... There are a few options that will serve you well.

+
disper -e #extend your display
+
+
disper -c #clone your display
+
+
disper -s #only your external display
+
+

+
+ + +
+
+

Translations:

+
    +
+
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/linux-external-display-with-disper.html.gz b/en/linux-external-display-with-disper.html.gz new file mode 100644 index 000000000..ac06097ea Binary files /dev/null and b/en/linux-external-display-with-disper.html.gz differ diff --git a/en/microservices_nodejs_express_rabbitmq_part_1.html b/en/microservices_nodejs_express_rabbitmq_part_1.html new file mode 100644 index 000000000..cd8b360c1 --- /dev/null +++ b/en/microservices_nodejs_express_rabbitmq_part_1.html @@ -0,0 +1,549 @@ + + + + + + + + Microservices with NodeJS, Express.js and RabbitMQ Part 1 - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+ + +
+

This is the first part of a microservices development series. The service will consist of the bellow architecture, where we will expose an image optimizer service that will forward the request to a RabbitMQ queue and answer with the bytecode of the optimized image. It shouldn't be a long series so let's see what we can do.

+Service architecture +

Let's get our environment working. First, we'll need to install the libraries that we'll use.

+

Create a dir and initialize the nodejs application inside it (npm init) and then let's install the deps.

+
    +
  • amqplib - AMQP lib to interact with rabbitmq
  • +
  • express - Do our basic rest API
  • +
  • express-fileupload - easy file upload parser
  • +
  • imagemin and imagemin-pngquant - our image compacter
  • +
+
npm install --save express amqplib express-fileupload imagemin imagemin-pngquant
+
+

Now let's write the entry points for our service, we'll have two basic entry points. The path / that will have a welcome message, the second path will be /upload and this is the one that will handle the image and produce a job for our workers.

+
const express = require('express');
+const fileUpload = require('express-fileupload');
+
+//Instantiate the app and set the fileupload parser to manage files
+const app = express();
+app.use(fileUpload());
+
+//Our index entry point
+app.get('/', (req, res) => res.send('Hello From ImageCompacter service'));
+
+//The path that will handle the image file and throw them to the queue
+app.post('/upload', (req, res) => {
+    //With express-fileupload we can grab the files like this
+    let img = req.files.image; //"image" is the name of the input
+
+    res.send('Not ready yet');
+});
+
+//Finally start the app with the given port number
+app.listen(4000, () => console.log('Example app listening on port 4000!'));
+
+

Let's check if it works, run the service with node.

+
node index.js
+Example app listening on port 4000!
+
+

Open the browser and check if it prints our hello message when accessing localhost:4000. Works? Greate. Now let's work with the image and see how we do it. To optimize our image, we'll use the library imagemin and imagemin-pngquant, it will be that simple for now, we'll work with rabbitmq latter.

+
const imagemin = require('imagemin');
+const imageminPngquant = require('imagemin-pngquant');
+//...
+
+//The path that will handle the image file and throw them to the queue
+app.post('/upload', (req, res) => {
+    let img = req.files.image; //"image" is the name of the input
+
+            imagemin.buffer(img.data, {
+        plugins: [imageminPngquant()]
+    })
+    .then(out => {
+        res.write(out,'binary');
+        res.end(null, 'binary');
+    });
+});
+
+    //...
+
+

Use Postman to test the request. To see if it will work, make a request to http://localhost:4000/upload with a formdata with a file. Select the "send and Download" instead of "Send" and you should have an image after that. Bellow an image of how your postman should be.

+Postman +

That's it for today, next week we'll change our code to use RabbitMQ.

+

+
+ + +
+
+

Translations:

+
    +
+
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/microservices_nodejs_express_rabbitmq_part_1.html.gz b/en/microservices_nodejs_express_rabbitmq_part_1.html.gz new file mode 100644 index 000000000..cfe72f91a Binary files /dev/null and b/en/microservices_nodejs_express_rabbitmq_part_1.html.gz differ diff --git a/en/microservices_nodejs_express_rabbitmq_part_2.html b/en/microservices_nodejs_express_rabbitmq_part_2.html new file mode 100644 index 000000000..461b11458 --- /dev/null +++ b/en/microservices_nodejs_express_rabbitmq_part_2.html @@ -0,0 +1,580 @@ + + + + + + + + Microservices with NodeJS, Express.js and RabbitMQ Part 2 - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+ + +
+

If you haven't read the part 1 go ahead and read it... It can be useful :). Or if for some reason you want to start now, you can grab the project where we stopped here and get along. On this part, we'll implement the RabbitMQ queue and see how we can get the best of our app and server with that.

+

Before we began coding, let's understand why we are going to use RabbitMQ if what we have now works? If you check again, you'll see how long it takes to answer the request with the optimized image. It takes a few seconds, so imagine an online service with thousands of request to optimize images (like TinyPNG) how long is it gonna take to answer every request? How much of your server is it gonna take? With only one service running, probably the server will crash.

+

With a queue, we can schedule the requests so we can use the amount of memory and processor that our server has, without taking more than we can. It's better to take a few seconds to answer the request then throw some error to the user. Want more? With RabbitMQ we can see how the queue is doing and we can add more consumers (workers) to it and get things done quicker and distribute the job.

+

First of all, we need an up and running Rabbit server, for the sake of simplicity, I'll use a Docker container with it inside.

+
docker run -d --name rabbit -p 5672:5672 -p 8080:15672 rabbitmq:3-management
+
+

You can see that we're running the rabbitmq:3-management image, which provides us a web interface to see how things are going. After that, if you look at our code you'll see that all the job is made at the '/upload' route, and that's what we'll change.

+

First, we need to understand what we need from RabbitMQ. We need something that, we send an image to a queue and get an optimized image back from that. There is a name for that, is RPC (remote procedure call) and there are two ways of doing this with rabbit. Both the ways you can see on their tutorial page. We'll use the approach that uses a global channel whose id is randomly generated (you'll use the name 'amq.rabbitmq.reply-to' but the rabbit will do the job).

+

Let's start importing the library, defining a few variables and defining a init function that will establish a connection with the rabbit server and create our RPC queue. The RPC queue it's where we'll receive the answer from the consumer (our worker).

+
//import the library
+const amqplib = require('amqplib');
+
+//queue channel
+let channel = null;
+//queue name
+const QUEUE = 'optimizeimg';
+
+//...
+
+function init() {
+    return require('amqplib').connect('amqp://localhost')
+        .then(conn => conn.createChannel())
+        .then(ch => {
+            channel = ch;
+
+            //this queue is a "Direct reply-to" read more at the docs
+            //When some msg comes in, we "emit" a message to the proper "correlationId" listener
+            ch.consume('amq.rabbitmq.reply-to', msg => eventEmitter.emit(msg.properties.correlationId, msg.content), {noAck: true});
+        });
+}
+
+//Random id generator
+function randomid() {
+    return new Date().getTime().toString() + Math.random().toString() + Math.random().toString();
+}
+
+app.post('/upload', (req, res) => {
+    let img = req.files.image;
+
+    let id = randomid();
+
+    //Event listener that will fire when the proper randomid is provided
+    eventEmitter.once(id, msg => {
+        res.write(msg, 'binary');
+        res.end(null, 'binary');
+    });
+
+    //Checks if the queue exists, and create it if needed.
+    channel.assertQueue(QUEUE)
+        //Sent the buffered img to the queue with the ID and the responseQueue
+        .then(() => channel.sendToQueue(QUEUE, img.data, {correlationId:id, replyTo: 'amq.rabbitmq.reply-to'}));
+
+});
+
+//Finally start the app with the given port number
+//now we initialize the rabbitmq connection before start the server
+init()
+    .then(() => app.listen(4000, () => console.log('Example app listening on port 4000!')))
+    .catch(err=>console.error(err));
+
+

Ok, now we have our server code rewritten so let's see our worker code. Create a file named 'worker.js' and let's see how it's gonna be. It's really simple. You initialize a connection with RabbitMQ too, create a channel, check if the queue exists and start watching for incoming messages. When an image arrives, we do the job with it and send back to the "replyTo" queue the optimized image for the proper sender (correlationId). In the end, we do an acknowledge of the message so it get's out from the queue.

+
const imagemin = require('imagemin');
+const imageminPngquant = require('imagemin-pngquant');
+
+let channel = null;
+const QUEUE = 'imgqueue';
+
+require('amqplib').connect('amqp://localhost')
+.then(conn =>conn.createChannel())
+.then(ch => {
+    ch.assertQueue(QUEUE)
+    .then(() => {
+        //Watch incomming messages
+        ch.consume(QUEUE, msg => {
+            imagemin.buffer(msg.content, {
+                plugins: [imageminPngquant()]
+            })
+            .then(out => {
+                //Send back to the sender (replyTo) queue and give the correlationId back
+                //so we can emit the event.
+                ch.sendToQueue(msg.properties.replyTo, out, {
+                    correlationId: msg.properties.correlationId
+                });
+
+                //Acknowledge the job done with the message.
+                ch.ack(msg);
+            });
+        });
+    });
+});
+
+

The key points here are. Open just one connection to the hole server. You CAN create one channel for every request that you receive, but it can take some time if you have a really big cluster of RabbitMQ. It was a quick tutorial, but I hope that it was able to clear a few questions that you might have when working with rabbit and express.

+

+
+ + +
+
+

Translations:

+
    +
+
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/microservices_nodejs_express_rabbitmq_part_2.html.gz b/en/microservices_nodejs_express_rabbitmq_part_2.html.gz new file mode 100644 index 000000000..919994d9b Binary files /dev/null and b/en/microservices_nodejs_express_rabbitmq_part_2.html.gz differ diff --git a/en/microsoft-against-covid.html b/en/microsoft-against-covid.html new file mode 100644 index 000000000..db6a400d2 --- /dev/null +++ b/en/microsoft-against-covid.html @@ -0,0 +1,511 @@ + + + + + + + + Microsoft Against Covid - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Microsoft Against Covid

+
+ +
+
+ +
+

Has your job been affected by covid? Well, last week I've posted on Grepora about a Free Certification Voucher that Microsoft was giving away at the Microsoft Ignite event. After that, I found that they were also giving a huge discount to people who have had their job affected by covid pandemic.

+

To see more details about if you were eligible, access https://docs.microsoft.com/en-us/learn/certifications/skillingoffer.

+
+ + +
+
+

Translations:

+ +
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/microsoft-against-covid.html.gz b/en/microsoft-against-covid.html.gz new file mode 100644 index 000000000..6d4eda9d8 Binary files /dev/null and b/en/microsoft-against-covid.html.gz differ diff --git a/en/monitoring-mysql-replication-with-powershell.html b/en/monitoring-mysql-replication-with-powershell.html new file mode 100644 index 000000000..40eb4366f --- /dev/null +++ b/en/monitoring-mysql-replication-with-powershell.html @@ -0,0 +1,576 @@ + + + + + + + + Monitoring MySQL Replication Status with PowerShell - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+ + +
+

I've been migration some bash scripts that I have to PowerShell, and it's time to migrate a script that monitors the replication of a MySQL database. The credit for the original script goes to Paweł. It's a simple script where I seek a few tags/fields that we get from SHOW SLAVE STATUS\G command, the fields are. Slave_IO_Running, Slave_SQL_Running, and Seconds_Behind_Master. I still need to figure out the proper way to store/read variables like usernames and passwords, if you have any tips, feel free to even make a pull request (here) at the git where I'll store some scripts.

+
<#
+   Variables definition
+#>
+$MaxSeconds = 120  # Max seconds behind master allowed
+$MysqlUser  = 'root'
+$MysqlPass  = ''
+
+$MailTo     = 'mauricio@sipmann.com'
+$MailFrom   = 'mauricio@sipmann.com'
+
+
+$data = $(mysql -u $MysqlUser -p"$MysqlPass" -e 'SHOW SLAVE STATUS \G')
+
+#Debug data
+#$data = Get-Content 'c:\temp\sampleresult.txt'
+
+<# Parse the data #>
+$IORunning   = (($data | Where-Object { $_ -match 'Slave_IO_Running:' }) -split '\s+')[2]
+$SQLRunning  = (($data | Where-Object { $_ -match 'Slave_SQL_Running:' }) -split '\s+')[2]
+$LastErrNo   = (($data | Where-Object { $_ -match 'Last_Errno' }) -split '\s+')[2]
+$SecondsBh   = [int](($data | Where-Object { $_ -match 'Seconds_Behind_Master' }) -split '\s+')[2]
+
+If ($IORunning -Eq 'No' -Or $SQLRunning -Eq 'No' -Or $SecondsBh -gt $MaxSeconds) {
+    $MailBody = '<h1>Problema na replicação</h1><br>'
+
+    $MailBody += '    IO Running: ' + ($IORunning)  + '<br>'
+    $MailBody += '   SQL Running: ' + ($SQLRunning) + '<br>'
+    $MailBody += 'Seconds Behind: ' + ($SecondsBh) + '<br>'
+    $MailBody += '   Last Err No: ' + ($LastErrNo) + '<br>'
+
+    <# Send e-mail, maybe some telegram message here too #>
+    Send-MailMessage -To $MailTo -From $MailFrom  -Subject 'Problemas na replicação' -bodyAsHtml $MailBody -Credential (Get-Credential) -SmtpServer 'smtp.office365.com' -Port 587 -UseSsl
+} Else {
+    Write-Host "Up and running"
+}
+

+
+ + +
+
+

Translations:

+ +
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/monitoring-mysql-replication-with-powershell.html.gz b/en/monitoring-mysql-replication-with-powershell.html.gz new file mode 100644 index 000000000..77ada72a6 Binary files /dev/null and b/en/monitoring-mysql-replication-with-powershell.html.gz differ diff --git a/en/monitoring-mysql-restarts-with-powershell.html b/en/monitoring-mysql-restarts-with-powershell.html new file mode 100644 index 000000000..e9464b501 --- /dev/null +++ b/en/monitoring-mysql-restarts-with-powershell.html @@ -0,0 +1,540 @@ + + + + + + + + Monitoring MySQL restarts with PowerShell - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Monitoring MySQL restarts with PowerShell

+
+ +
+
+ +
+

Hey folks, it's time for another PowerShell script. If you haven't seen the other ones, check the links below.

+ +

Well, this one it's a pretty simple script, but again, if your customer doesn't have a Zabbix server or doesn't allow you to setup one to do the monitoring, a set of scripts can be handy. We start executing some basic query SHOW GLOBAL STATUS LIKE 'Uptime', with that we'll get exactly what we're looking for.

+

If for some reason, the command fails (watch for the "global" variable called $lastExitCode), we send an e-mail telling you about that connection problem.

+

And then, we get to the part where we parse the value, this one is pretty similar to the parse we did on the first post about using PowerShell to monitor MySQL. But we basically look for the Value line, split it by space and then parse the second position to an integer. And then all we have to do is check if the uptime is lower than our threshold, if it is we send an e-mail.

+
$MailFrom = 'maurio[at]sipmann.com'
+$MailTo   = 'mauricio[at]sipmann.com'
+$MysqlHost = '127.0.0.1'
+$MysqlUser = 'root'
+$MysqlPass = '123'
+
+
+$data = $(mysql -h $MysqlHost -u $MysqlUser -p"$MysqlPass" -e "SHOW GLOBAL STATUS LIKE 'Uptime' \G")
+
+<# Unable to execute the sql Command #>
+if ($lastExitCode -eq 1) {
+    Send-MailMessage -To $MailTo -From $MailFrom  -Subject 'Connection problem' -bodyAsHtml "Connection problem on host ${MysqlHost}" -Credential Get-Credential -SmtpServer 'smtp.office365.com' -Port 587 -UseSsl
+    exit
+}
+
+$UpTime   = [int](($data | Where-Object { $_ -match 'Value:' }) -split '\s+')[2]
+
+<# If the uptime is lower then 20 minutes #>
+if ($UpTime -lt 1200) {
+    Send-MailMessage -To $MailTo -From $MailFrom -Subject "MySQL Restarted" -bodyAsHtml "MySQL host ${MysqlHost} restarted less than 20 minutes ago" -Credential Get-Credential -SmtpServer 'smtp.office365.com' -Port 587 -UseSsl
+}
+
+ +

This script (and the other ones I use) is available at my GitHub here. Keep in mind that the ones on the GitHub repo, are a little different from here.

+
+ + +
+
+

Translations:

+ +
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/monitoring-mysql-restarts-with-powershell.html.gz b/en/monitoring-mysql-restarts-with-powershell.html.gz new file mode 100644 index 000000000..a3f5d364b Binary files /dev/null and b/en/monitoring-mysql-restarts-with-powershell.html.gz differ diff --git a/en/monitoring-website-heath-with-azure-functions.html b/en/monitoring-website-heath-with-azure-functions.html new file mode 100644 index 000000000..980b685d3 --- /dev/null +++ b/en/monitoring-website-heath-with-azure-functions.html @@ -0,0 +1,619 @@ + + + + + + + + Monitoring a Website heath with Azure Functions - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+ + +
+

Sometimes you get your self in need to monitor a website's health or it's content for changes. Of course, there's plenty of options out there, but for the sake of curiosity, let's code our own to see what we can do. First things first. Everything you'll see here, you can achieve with the free tier of azure.

+

The main idea of our app will be to monitor website health (status code). To create a new Azure Function Project, follow the steps below.

+

Steps to create a azure function project

+

After creating the project, you'll have a few files. Open your main file and start coding. The main file will have a function called Run and you can code your request method. I've created an async method to make the request and log the output at the console. The full code you can see below.

+
using System;
+using System.Linq;
+using System.Net.Http;
+using System.Threading.Tasks;
+using Microsoft.Azure.WebJobs;
+using Microsoft.Azure.WebJobs.Host;
+using Microsoft.Extensions.Logging;
+
+namespace Sipmann.CheckMySite
+{
+    public static class HttpCheck
+    {
+
+        private static async Task GetTask(string url, ILogger log)
+        {
+            var request = new HttpRequestMessage(HttpMethod.Get, url);
+
+            var client = new HttpClient();
+            var response = await client.SendAsync(request);
+
+            if (response.IsSuccessStatusCode)
+            {
+                log.LogInformation($"URL ${url} esta OK");
+            }
+            else
+            {
+                log.LogInformation($"URL ${url} não esta OK");
+            }
+        }
+
+        [FunctionName("HttpCheck")]
+        public static void Run([TimerTrigger("0 */5 * * * *")]TimerInfo myTimer, ILogger log)
+        {
+            var urls = new[]{"https://www.sipmann.com", "https://www.canezecanez.com.br"};
+
+            // Start every request and wait for them all to complete
+            Task.WaitAll(urls.Select(url => GetTask(url, log)).ToArray());
+            log.LogInformation($"Finalizou a fila");
+        }
+    }
+}
+
+ +

Now you can enhance the function and maybe send some alerts like a Telegram message when one of your sites went down.

+
+ + +
+
+

Translations:

+ +
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/monitoring-website-heath-with-azure-functions.html.gz b/en/monitoring-website-heath-with-azure-functions.html.gz new file mode 100644 index 000000000..375d76b45 Binary files /dev/null and b/en/monitoring-website-heath-with-azure-functions.html.gz differ diff --git a/en/mysql-dual-password-functionality.html b/en/mysql-dual-password-functionality.html new file mode 100644 index 000000000..6fad2d654 --- /dev/null +++ b/en/mysql-dual-password-functionality.html @@ -0,0 +1,520 @@ + + + + + + + + Changing a MySQL user password across multiple application instances without downtime - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+ + +
+

Do you need to change the password of a MySQL user that it's being used in an application, and can't allow a single downtime? Well, MySQL 8.0.14 came with a feature called Dual Password Support, with it you can change the password keeping the previous password as a kind of backup. That way you still can log in using the old password or can start using the new one. With that, the password change workflow it's the following.

+

1) Change password keeping the old one;

+

2) Deploy the new config to your app/cluster;

+

3) Discard the old password.

+

To change the password and keep the old one, you have the following command.

+
ALTER USER 'appuser'@'localhost' IDENTIFIED BY 'new_password' RETAIN CURRENT PASSWORD;
+
+ +

To discard the old one, run the following.

+
ALTER USER 'appuser'@'localhost' DISCARD OLD PASSWORD;
+
+ +

And you are done. Hope you find it as useful as I :)

+
+ + +
+
+

Translations:

+ +
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/mysql-dual-password-functionality.html.gz b/en/mysql-dual-password-functionality.html.gz new file mode 100644 index 000000000..78cece55d Binary files /dev/null and b/en/mysql-dual-password-functionality.html.gz differ diff --git a/en/now_posting_on_grepora.html b/en/now_posting_on_grepora.html new file mode 100644 index 000000000..ebf7dbf62 --- /dev/null +++ b/en/now_posting_on_grepora.html @@ -0,0 +1,407 @@ + + + + + + + + Now posting on Grepora - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Now posting on Grepora

+
+ +
+
+ +
+

A few weeks ago I started posting at Grepora blog. If you like or are looking for some Oracle related stuff, Grepora it's a good place to go and spend a time reading :). From time to time I'll be posting there, it doesn't mean that this blog will be closed or anything like that, but probably this one will be more focused on Front-end stuff, a few tricks with linux and a lil less with Java.

+

+
+ + +
+
+

Translations:

+
    +
+
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/now_posting_on_grepora.html.gz b/en/now_posting_on_grepora.html.gz new file mode 100644 index 000000000..bcfc36d75 Binary files /dev/null and b/en/now_posting_on_grepora.html.gz differ diff --git a/en/pages/about.html b/en/pages/about.html new file mode 100644 index 000000000..33f451dc3 --- /dev/null +++ b/en/pages/about.html @@ -0,0 +1,304 @@ + + + + + + + + About - Sipmann + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+

About

+ +
+ +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/pages/about.html.gz b/en/pages/about.html.gz new file mode 100644 index 000000000..c365de6e6 Binary files /dev/null and b/en/pages/about.html.gz differ diff --git a/en/pages/cartao-pt.html b/en/pages/cartao-pt.html new file mode 100644 index 000000000..2c2aa9085 --- /dev/null +++ b/en/pages/cartao-pt.html @@ -0,0 +1,480 @@ + + + + + + + + cartao - Sipmann + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+

cartao

+ +
+ + +
+
+ +
+
+
+
+

Consultoria Cloud

+

+ Projetos de implantação e acompanhamento de sua cloud. Otimize seus custos de infraestrutura levando o seu DR para a nuvem da forma mais transparente. +

+

Mais Detalhes

+
+
+
+
+
+
+ +
+
+
+
+

Gestão De Banco

+

+ Gerenciamento, manutenção e acompanhamento do seu banco de dados SQL Server. Com foco na segurança e velocidade de resposta em consultas. +

+

Mais Detalhes

+
+
+
+
+
+
+ +
+
+
+
+

Power BI

+

+ Dashboards analíticos para análise e tomadas de decisões do seu negócio. Baixe um dashboard e analise o faturamento do seu ERP Protheus. +

+

Mais Detalhes

+
+
+
+
+
+
+ +
+
+
+
+

Monitoramento

+

+ Monitoramento de sua infraestrutura, aplicações e bancos de dados. Fornecendo relatórios detalhados desde avisos, erros até o uptime de serviços críticos. +

+

Mais Detalhes

+
+
+
+
+
+
+ +
+
+

Consultoria cloud

+
+
+

+
+
+ +
+
+

Meus Serviços

+
+
+

Has your job been affected by covid? Well, last week I've posted on Grepora about a Free Certification Voucher that Microsoft was giving away at the Microsoft Ignite event. After that, I found that they were also giving a huge discount to people who have had their job affected by …

+
+ + +
+

+ View comments +

+
+
+
+
+ + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/pages/cartao-pt.html.gz b/en/pages/cartao-pt.html.gz new file mode 100644 index 000000000..a1e690047 Binary files /dev/null and b/en/pages/cartao-pt.html.gz differ diff --git a/en/reading-files-java-readAllBytes-outofmemory.html b/en/reading-files-java-readAllBytes-outofmemory.html new file mode 100644 index 000000000..02adcdfb3 --- /dev/null +++ b/en/reading-files-java-readAllBytes-outofmemory.html @@ -0,0 +1,511 @@ + + + + + + + + Java - Files.readAllBytes throws OutOfMemory - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Java - Files.readAllBytes throws OutOfMemory

+
+ +
+
+ +
+

When you need to interact with files, there's the possibility to read all bytes from the file with Files.readAllBytes. But be aware of the kinds of files your application will deal with because the Java API files have a limit for the buffer that is defined as Integer.MAX_VALUE as you can see above or at the OpenJDK sources.

+
public static byte[] readAllBytes(Path path) throws IOException {
+    try (FileChannel fc = FileChannel.open(path)) {
+        long size = fc.size();
+        if (size > (long)Integer.MAX_VALUE)
+            throw new OutOfMemoryError("Required array size too large");
+
+        byte[] arr = new byte[(int)size];
+        ByteBuffer bb = ByteBuffer.wrap(arr);
+        while (bb.hasRemaining()) {
+            if (fc.read(bb) < 0) {
+                // truncated
+                break;
+            }
+        }
+
+        int nread = bb.position();
+        return (nread == size) ? arr : Arrays.copyOf(arr, nread);
+    }
+}
+
+

With that in mind, check if isn't better read chunks of bytes e work with that slice in exchange of loading the whole file into the memory ;). Above a simple example of how you can read chunks of bytes from the file.

+
byte[] buffer = new byte[1024];
+FileInputStream in = new FileInputStream(file);
+int rc = in.read(buffer);
+while (rc != -1)
+{
+    //crazy stuff here with buffer
+    rc = in.read(buffer);
+}
+
+

+
+ + +
+
+

Translations:

+
    +
+
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/reading-files-java-readAllBytes-outofmemory.html.gz b/en/reading-files-java-readAllBytes-outofmemory.html.gz new file mode 100644 index 000000000..aca5a732c Binary files /dev/null and b/en/reading-files-java-readAllBytes-outofmemory.html.gz differ diff --git a/en/removing-user-from-sql-server-database.html b/en/removing-user-from-sql-server-database.html new file mode 100644 index 000000000..4a53643ce --- /dev/null +++ b/en/removing-user-from-sql-server-database.html @@ -0,0 +1,520 @@ + + + + + + + + Removing a user from SQL Server database who owns a schema - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Removing a user from SQL Server database who owns a schema

+
+ +
Updated: 21 October 2020 +
+
+ +
+

Your customer urge you to drop a user from the MsSQL Server database, but you stuck with the following related error:

+
Error: 15138 The database principal owns a schema in the database, and cannot be dropped.
+
+ +

That means that the user owns one or more shcemas of your database. If you don't have access to the SSMS to see which schema or objects the user owns, the following SQL should do the job.

+
USE [DATABASENAME]
+GO
+
+select so.name Objeto, su.name Owner
+from sys.schemas so
+inner join sysusers su on so.principal_id = su.uid
+where su.name = 'username'
+
+select so.name Objeto, su.name Owner, so.xtype Tipo
+from sys.sysobjects so
+inner join sysusers su on so.uid = su.uid
+where su.name = 'username'
+
+ +

Once you have the objects/schemas owned by the user, you can change them with the following SQL (schema change sample):

+
USE [DATABASENAME]
+GO
+ALTER AUTHORIZATION ON SCHEMA::[db_datareader] TO [dbo] -- new owner username
+ALTER AUTHORIZATION ON SCHEMA::[db_datawriter] TO [dbo]
+GO
+
+ +

Then you're ready to drop the user DROP USER [username]

+

How to list all the schemas and it's owners?

+

Here's a script to list schemas and it's owners.

+
USE [DATABASENAME]
+GO
+SELECT
+    schema_name(schema_id) AS schemaname,
+    user_name(schm.principal_id) AS username, *
+FROM sys.schemas AS schm
+GO
+

+
+ + +
+
+

Translations:

+ +
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/removing-user-from-sql-server-database.html.gz b/en/removing-user-from-sql-server-database.html.gz new file mode 100644 index 000000000..b94cd337e Binary files /dev/null and b/en/removing-user-from-sql-server-database.html.gz differ diff --git a/en/scaffolding_react_app_with_parcel_yeoman.html b/en/scaffolding_react_app_with_parcel_yeoman.html new file mode 100644 index 000000000..55767898f --- /dev/null +++ b/en/scaffolding_react_app_with_parcel_yeoman.html @@ -0,0 +1,505 @@ + + + + + + + + Scaffolding a React app with Parcel and Yeoman - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+ + +
+

Since Parcel JS arrived, I've been using it a lot as an awesome alternative for WebPack. Webpack isn't bad but IMO it's too complex for the job and parcel do the same (at least the basic) with almost zero configuration. But if you need to create many apps (like a react app) over and over again, it get's a lil boring following the basic steps.

+
npm init -y
+npm install --save react
+npm install --save react-dom
+npm install --save-dev parcel-bundler
+npm install --save-dev babel-preset-env
+npm install --save-dev babel-preset-react
+
+#create .babelrc file
+#create html, css, jsx files
+
+parcel index.html
+
+

It's not a hard job, a simple shell script do the job, but what if you need some IFs when creating the app, or even change a few things at the package.json? A shell script still does the job, but come on... There is a better way. Yeoman is here for you. I've already talked about it on another post (Portuguese post).

+

Straight to the point, I've released a Yeoman generator to get the things a lil quicker. The name is generator-parcel-react and it still lacks a few things that I will deal with soon. It's pretty simple to use it.

+
#First time only
+npm install -g yo
+npm install -g generator-parcel-react
+
+#every time you create a new app
+yo parcel-react
+
+

And that's it. Right now you can scaffold and app with React, SASS and React Router. Hope you like it and feel free to ask new features.

+

+
+ + +
+
+

Translations:

+
    +
+
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/scaffolding_react_app_with_parcel_yeoman.html.gz b/en/scaffolding_react_app_with_parcel_yeoman.html.gz new file mode 100644 index 000000000..3c1aee4b2 Binary files /dev/null and b/en/scaffolding_react_app_with_parcel_yeoman.html.gz differ diff --git a/en/select_specific_fields_with_efcore.html b/en/select_specific_fields_with_efcore.html new file mode 100644 index 000000000..00e291bab --- /dev/null +++ b/en/select_specific_fields_with_efcore.html @@ -0,0 +1,506 @@ + + + + + + + + How to set columns on select using Entity Framework - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+ + +
+

So, you use Entity Framework Core, and you usually code your selects like the following, maybe you are getting too much data.

+
var products = Products
+    .Where(p => p.UnitsInStock > 0)
+    .OrderBy(p => p.ProductName)
+    .ToList()
+
+ +

Running the query above, on my table, you'll get the following output, take a look at how many columns you are getting back from your database.

+

Screenshot with every single column

+

In my case, I only care about the Title, PublishedData, and a small description. So to get back only these fields, we have a few options. In the first one, we'll set the fields and return them as a dynamic object, the second one, is to give the .NET a class to use.

+
var products = Products
+
+    .Select(p => new {p.ProductID, p.ProductName, p.UnitsInStock, p.UnitPrice})
+    //.Select(p => new ProductDTO {p.ProductID, p.ProductName, p.UnitsInStock, p.UnitPrice})
+
+    .Where(p => p.UnitsInStock > 0)
+    .OrderBy(p => p.ProductName)
+    .ToList()
+
+ +

Screenshot with fewer columns and also fewer data size

+
+ + +
+
+

Translations:

+ +
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/select_specific_fields_with_efcore.html.gz b/en/select_specific_fields_with_efcore.html.gz new file mode 100644 index 000000000..40feaa2f0 Binary files /dev/null and b/en/select_specific_fields_with_efcore.html.gz differ diff --git a/en/sitemap.xml b/en/sitemap.xml new file mode 100644 index 000000000..d8c09b54b --- /dev/null +++ b/en/sitemap.xml @@ -0,0 +1,881 @@ + + + + +https://www.sipmann.com/en/ +2024-02-14T00:32:49-00:00 +daily +0.4 + + + +https://www.sipmann.com/en/tags.html +2024-02-14T00:32:49-00:00 +daily +0.4 + + + +https://www.sipmann.com/en/categories.html +2024-02-14T00:32:49-00:00 +daily +0.4 + + + +https://www.sipmann.com/en/authors.html +2024-02-14T00:32:49-00:00 +daily +0.4 + + + +https://www.sipmann.com/en/archives.html +2024-02-14T00:32:49-00:00 +daily +0.4 + + + +https://www.sipmann.com/en/monitoring-mysql-restarts-with-powershell.html +2020-12-21T13:30:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/en/mysql-dual-password-functionality.html +2020-12-09T13:40:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/en/apache-nifi-json-to-sql-replacing-underscore.html +2020-12-02T14:00:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/en/blocking-user-on-sql-server-based-on-schedule.html +2020-11-14T07:00:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/en/select_specific_fields_with_efcore.html +2020-10-28T19:00:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/en/zabbix-running-on-low-memory-mode.html +2020-10-20T19:00:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/en/monitoring-mysql-replication-with-powershell.html +2020-10-14T19:00:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/en/microsoft-against-covid.html +2020-10-03T19:00:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/en/the-power-of-powershell.html +2020-09-21T19:00:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/en/top_level_statement_csharp_9.html +2020-07-29T19:00:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/en/zabbix-poller-processes-more-than-75.html +2020-07-02T19:00:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/en/monitoring-website-heath-with-azure-functions.html +2020-06-22T19:00:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/en/azure-data-fundamentals-certification-80-discount.html +2020-06-09T12:30:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/en/zabbix-icmp-pinger-processes-more-than-75.html +2020-05-25T16:00:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/en/zabbix-server-out-of-memory-crash.html +2020-02-27T19:00:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/en/flutter_with_firebase_auth_crashing.html +2019-10-03T19:00:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/en/removing-user-from-sql-server-database.html +2020-10-21T18:40:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/en/limiting-connection-resources-sql-server.html +2019-08-12T12:00:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/en/using_git_hooks_easy_your_life.html +2019-07-30T20:00:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/en/microservices_nodejs_express_rabbitmq_part_2.html +2018-04-13T13:00:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/en/microservices_nodejs_express_rabbitmq_part_1.html +2018-04-04T11:25:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/en/connecting_to_database_through_ssh.html +2018-03-29T10:03:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/en/now_posting_on_grepora.html +2018-03-24T00:40:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/en/scaffolding_react_app_with_parcel_yeoman.html +2018-03-17T13:00:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/en/cloud-not-open-connection-java-mysql-hibernate.html +2018-03-09T12:35:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/en/socketException-protocol-family-unavailable-java-docker-wildfly.html +2018-03-04T17:40:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/en/linux-external-display-with-disper.html +2018-02-27T12:40:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/en/reading-files-java-readAllBytes-outofmemory.html +2018-02-17T13:00:00-02:00 +monthly +0.8 + + + +https://www.sipmann.com/en/category/azure.html +2020-10-03T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/category/flutter.html +2019-10-03T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/category/front-end.html +2018-04-13T13:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/category/java.html +2018-03-09T12:35:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/category/linux.html +2020-10-20T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/category/mysql.html +2020-12-09T13:40:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/category/net.html +2020-10-28T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/category/powershell.html +2020-12-21T13:30:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/category/random.html +2018-03-24T00:40:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/category/sql-server.html +2020-11-14T07:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/category/tools.html +2020-12-02T14:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/mysql.html +2020-12-21T13:30:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/mysql-restart.html +2020-12-21T13:30:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/powershell-monitoring.html +2020-12-21T13:30:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/mysql-dual-password.html +2020-12-09T13:40:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/apache-nifi.html +2020-12-02T14:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/convertjsontosql.html +2020-12-02T14:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/replacing-underscore.html +2020-12-02T14:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/sqlserver.html +2020-11-14T07:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/user.html +2020-11-14T07:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/time-schedule-blocking.html +2020-11-14T07:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/dotnet.html +2020-10-28T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/dotnet-core.html +2020-10-28T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/entity-framework.html +2020-10-28T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/ef-core.html +2020-10-28T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/specify-columns.html +2020-10-28T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/zabbix.html +2020-10-20T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/shell.html +2020-10-20T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/low-memory.html +2020-10-20T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/cache.html +2020-10-20T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/mysql-replication.html +2020-10-14T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/powershell.html +2020-10-14T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/powershell-mail.html +2020-10-14T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/azure.html +2020-10-03T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/certification.html +2020-10-03T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/microsoft.html +2020-10-03T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/script.html +2020-09-21T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/getchild-item.html +2020-09-21T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/remove-item.html +2020-09-21T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/stop-proccess.html +2020-09-21T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/c.html +2020-07-29T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/net.html +2020-07-29T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/zabbix-poller.html +2020-07-02T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/poller-proccess-more-than-75.html +2020-07-02T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/azure-devops.html +2020-06-22T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/monitor-website.html +2020-06-22T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/azure-fundamentals.html +2020-06-09T12:30:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/azure-certification.html +2020-06-09T12:30:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/discount.html +2020-06-09T12:30:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/icmp-pinger.html +2020-05-25T16:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/icmp-pinger-more-than-75.html +2020-05-25T16:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/zabbix-server.html +2020-05-25T16:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/out-of-memory.html +2020-02-27T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/crash.html +2020-02-27T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/flutter.html +2019-10-03T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/firebase.html +2019-10-03T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/arraymap.html +2019-10-03T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/noclassdeffound.html +2019-10-03T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/the-database-principal-owns-a-schema.html +2020-10-21T18:40:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/resource-governor.html +2019-08-12T12:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/git.html +2019-07-30T20:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/pre-commit.html +2019-07-30T20:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/hooks.html +2019-07-30T20:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/nodejs.html +2018-04-13T13:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/microservices.html +2018-04-13T13:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/rabbitmq.html +2018-04-13T13:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/expressjs.html +2018-04-13T13:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/imagemin.html +2018-04-13T13:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/imagemin-pngquant.html +2018-04-13T13:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/node-js.html +2018-04-13T13:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/openssh.html +2018-03-29T10:03:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/tunnel.html +2018-03-29T10:03:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/ssh-tunnel.html +2018-03-29T10:03:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/ssh.html +2018-03-29T10:03:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/through-firewall.html +2018-03-29T10:03:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/grepora.html +2018-03-24T00:40:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/random.html +2018-03-24T00:40:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/yeoman.html +2018-03-17T13:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/parcel.html +2018-03-17T13:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/react.html +2018-03-17T13:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/java.html +2018-03-09T12:35:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/hibernate.html +2018-03-09T12:35:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/wildfly.html +2018-03-04T17:40:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/docker.html +2018-03-04T17:40:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/javanetsocketexception.html +2018-03-04T17:40:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/protocol-family-unavailable.html +2018-03-04T17:40:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/linux.html +2018-02-27T12:40:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/external-display.html +2018-02-27T12:40:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/disper.html +2018-02-27T12:40:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/filesreadallbytes.html +2018-02-17T13:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/tag/outofmemory.html +2018-02-17T13:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/en/author/mauricio-camargo-sipmann.html +2020-12-21T13:30:00-03:06 +daily +0.4 + + + diff --git a/en/sitemap.xml.gz b/en/sitemap.xml.gz new file mode 100644 index 000000000..e174b54d9 Binary files /dev/null and b/en/sitemap.xml.gz differ diff --git a/en/socketException-protocol-family-unavailable-java-docker-wildfly.html b/en/socketException-protocol-family-unavailable-java-docker-wildfly.html new file mode 100644 index 000000000..4112676cc --- /dev/null +++ b/en/socketException-protocol-family-unavailable-java-docker-wildfly.html @@ -0,0 +1,491 @@ + + + + + + + + Solving java.net.SocketException: Protocol family unavailable on a Java + Docker + WildFly - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+ + +
+

On the last days I've been playing with WildFly Swarm and I decided to deploy a simple app with Docker. Should work fine, at least that was what I thought. Built a container with the following Dockerfile and instead of a working web app, all that I got was the error java.net.SocketException: Protocol family unavailable.

+
FROM java:openjdk-8-jdk
+
+COPY target/issues.jar /opt/issues.jar
+
+EXPOSE 8080
+
+CMD ["java","-jar","/opt/issues.jar"]
+
+

For some reason, WildFly and Java decided to use the IPv6 network interface from Docker instead the v4, so all you have to do is tell Java to prefer IPv4 instead with the following configuration option in your pom.xml file inside your WildFly plugin.

+
<plugin>
+        <groupId>org.wildfly.swarm</groupId>
+        <artifactId>wildfly-swarm-plugin</artifactId>
+        <version>2018.2.0</version>
+
+        <!-- ADD THIS -->
+        <configuration>
+          <mainClass>org.wildfly.swarm.examples.netflix.ribbon.frontend.Main</mainClass>
+          <properties>
+                <java.net.preferIPv4Stack>true</java.net.preferIPv4Stack>
+          </properties>
+        </configuration>
+
+

Another way to solve is adding the same properties to the run command at the Dockerfile, so you choose where you'll add it. Bellow the Dockerfile solution.

+
FROM java:openjdk-8-jdk
+ENV JAVA_OPTS="-Djava.net.preferIPv4Stack=true -Djava.net.preferIPv4Addresses=true"
+
+COPY target/issues.jar /opt/issues.jar
+
+EXPOSE 8080
+
+ENTRYPOINT exec java $JAVA_OPTS -jar /opt/issues.jar
+
+

+
+ + +
+
+

Translations:

+ +
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/socketException-protocol-family-unavailable-java-docker-wildfly.html.gz b/en/socketException-protocol-family-unavailable-java-docker-wildfly.html.gz new file mode 100644 index 000000000..fbe2b250e Binary files /dev/null and b/en/socketException-protocol-family-unavailable-java-docker-wildfly.html.gz differ diff --git a/en/tag/apache-nifi.html b/en/tag/apache-nifi.html new file mode 100644 index 000000000..9327f29f1 --- /dev/null +++ b/en/tag/apache-nifi.html @@ -0,0 +1,296 @@ + + + + + + + + Apache Nifi - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Apache Nifi

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/apache-nifi.html.gz b/en/tag/apache-nifi.html.gz new file mode 100644 index 000000000..c8ca6b247 Binary files /dev/null and b/en/tag/apache-nifi.html.gz differ diff --git a/en/tag/arraymap.html b/en/tag/arraymap.html new file mode 100644 index 000000000..34eca1f28 --- /dev/null +++ b/en/tag/arraymap.html @@ -0,0 +1,296 @@ + + + + + + + + ArrayMap - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

ArrayMap

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/arraymap.html.gz b/en/tag/arraymap.html.gz new file mode 100644 index 000000000..469cb849e Binary files /dev/null and b/en/tag/arraymap.html.gz differ diff --git a/en/tag/azure-certification.html b/en/tag/azure-certification.html new file mode 100644 index 000000000..7807221de --- /dev/null +++ b/en/tag/azure-certification.html @@ -0,0 +1,296 @@ + + + + + + + + Azure Certification - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Azure Certification

+
+ + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/azure-certification.html.gz b/en/tag/azure-certification.html.gz new file mode 100644 index 000000000..d9a3afb87 Binary files /dev/null and b/en/tag/azure-certification.html.gz differ diff --git a/en/tag/azure-devops.html b/en/tag/azure-devops.html new file mode 100644 index 000000000..30e606b70 --- /dev/null +++ b/en/tag/azure-devops.html @@ -0,0 +1,296 @@ + + + + + + + + Azure Devops - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Azure Devops

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/azure-devops.html.gz b/en/tag/azure-devops.html.gz new file mode 100644 index 000000000..697035d97 Binary files /dev/null and b/en/tag/azure-devops.html.gz differ diff --git a/en/tag/azure-fundamentals.html b/en/tag/azure-fundamentals.html new file mode 100644 index 000000000..f038fcb74 --- /dev/null +++ b/en/tag/azure-fundamentals.html @@ -0,0 +1,296 @@ + + + + + + + + Azure Fundamentals - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Azure Fundamentals

+
+ + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/azure-fundamentals.html.gz b/en/tag/azure-fundamentals.html.gz new file mode 100644 index 000000000..74996d29c Binary files /dev/null and b/en/tag/azure-fundamentals.html.gz differ diff --git a/en/tag/azure.html b/en/tag/azure.html new file mode 100644 index 000000000..3e60da0ea --- /dev/null +++ b/en/tag/azure.html @@ -0,0 +1,326 @@ + + + + + + + + Azure - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/azure.html.gz b/en/tag/azure.html.gz new file mode 100644 index 000000000..6553052ca Binary files /dev/null and b/en/tag/azure.html.gz differ diff --git a/en/tag/c.html b/en/tag/c.html new file mode 100644 index 000000000..4e1d68f35 --- /dev/null +++ b/en/tag/c.html @@ -0,0 +1,306 @@ + + + + + + + + C# - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/c.html.gz b/en/tag/c.html.gz new file mode 100644 index 000000000..94180cccf Binary files /dev/null and b/en/tag/c.html.gz differ diff --git a/en/tag/cache.html b/en/tag/cache.html new file mode 100644 index 000000000..fe839f43e --- /dev/null +++ b/en/tag/cache.html @@ -0,0 +1,296 @@ + + + + + + + + Cache - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Cache

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/cache.html.gz b/en/tag/cache.html.gz new file mode 100644 index 000000000..42f9b13b4 Binary files /dev/null and b/en/tag/cache.html.gz differ diff --git a/en/tag/certification.html b/en/tag/certification.html new file mode 100644 index 000000000..6192f9cff --- /dev/null +++ b/en/tag/certification.html @@ -0,0 +1,296 @@ + + + + + + + + Certification - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Certification

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/certification.html.gz b/en/tag/certification.html.gz new file mode 100644 index 000000000..92904e34b Binary files /dev/null and b/en/tag/certification.html.gz differ diff --git a/en/tag/convertjsontosql.html b/en/tag/convertjsontosql.html new file mode 100644 index 000000000..388f52d36 --- /dev/null +++ b/en/tag/convertjsontosql.html @@ -0,0 +1,296 @@ + + + + + + + + ConvertJSONToSQL - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

ConvertJSONToSQL

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/convertjsontosql.html.gz b/en/tag/convertjsontosql.html.gz new file mode 100644 index 000000000..be14bea3c Binary files /dev/null and b/en/tag/convertjsontosql.html.gz differ diff --git a/en/tag/crash.html b/en/tag/crash.html new file mode 100644 index 000000000..22ba845a7 --- /dev/null +++ b/en/tag/crash.html @@ -0,0 +1,296 @@ + + + + + + + + Crash - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Crash

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/crash.html.gz b/en/tag/crash.html.gz new file mode 100644 index 000000000..3f9b3cf71 Binary files /dev/null and b/en/tag/crash.html.gz differ diff --git a/en/tag/discount.html b/en/tag/discount.html new file mode 100644 index 000000000..814c764c4 --- /dev/null +++ b/en/tag/discount.html @@ -0,0 +1,296 @@ + + + + + + + + Discount - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/discount.html.gz b/en/tag/discount.html.gz new file mode 100644 index 000000000..287007416 Binary files /dev/null and b/en/tag/discount.html.gz differ diff --git a/en/tag/disper.html b/en/tag/disper.html new file mode 100644 index 000000000..c974c339c --- /dev/null +++ b/en/tag/disper.html @@ -0,0 +1,296 @@ + + + + + + + + disper - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+ +
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/disper.html.gz b/en/tag/disper.html.gz new file mode 100644 index 000000000..b2adb47c6 Binary files /dev/null and b/en/tag/disper.html.gz differ diff --git a/en/tag/docker.html b/en/tag/docker.html new file mode 100644 index 000000000..7423d2112 --- /dev/null +++ b/en/tag/docker.html @@ -0,0 +1,296 @@ + + + + + + + + Docker - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/docker.html.gz b/en/tag/docker.html.gz new file mode 100644 index 000000000..0ab4f165d Binary files /dev/null and b/en/tag/docker.html.gz differ diff --git a/en/tag/dotnet-core.html b/en/tag/dotnet-core.html new file mode 100644 index 000000000..4506b5f85 --- /dev/null +++ b/en/tag/dotnet-core.html @@ -0,0 +1,316 @@ + + + + + + + + DotNet Core - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/dotnet-core.html.gz b/en/tag/dotnet-core.html.gz new file mode 100644 index 000000000..f5255a2d4 Binary files /dev/null and b/en/tag/dotnet-core.html.gz differ diff --git a/en/tag/dotnet.html b/en/tag/dotnet.html new file mode 100644 index 000000000..afd18a1fe --- /dev/null +++ b/en/tag/dotnet.html @@ -0,0 +1,316 @@ + + + + + + + + DotNet - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/dotnet.html.gz b/en/tag/dotnet.html.gz new file mode 100644 index 000000000..53c89a928 Binary files /dev/null and b/en/tag/dotnet.html.gz differ diff --git a/en/tag/ef-core.html b/en/tag/ef-core.html new file mode 100644 index 000000000..fa6c25513 --- /dev/null +++ b/en/tag/ef-core.html @@ -0,0 +1,296 @@ + + + + + + + + EF Core - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/ef-core.html.gz b/en/tag/ef-core.html.gz new file mode 100644 index 000000000..d1b796dfb Binary files /dev/null and b/en/tag/ef-core.html.gz differ diff --git a/en/tag/entity-framework.html b/en/tag/entity-framework.html new file mode 100644 index 000000000..3de613a16 --- /dev/null +++ b/en/tag/entity-framework.html @@ -0,0 +1,296 @@ + + + + + + + + Entity Framework - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Entity Framework

+
+ + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/entity-framework.html.gz b/en/tag/entity-framework.html.gz new file mode 100644 index 000000000..9d43094e2 Binary files /dev/null and b/en/tag/entity-framework.html.gz differ diff --git a/en/tag/expressjs.html b/en/tag/expressjs.html new file mode 100644 index 000000000..40e6a83cf --- /dev/null +++ b/en/tag/expressjs.html @@ -0,0 +1,306 @@ + + + + + + + + expressjs - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/expressjs.html.gz b/en/tag/expressjs.html.gz new file mode 100644 index 000000000..507f80501 Binary files /dev/null and b/en/tag/expressjs.html.gz differ diff --git a/en/tag/external-display.html b/en/tag/external-display.html new file mode 100644 index 000000000..bff2a39c2 --- /dev/null +++ b/en/tag/external-display.html @@ -0,0 +1,296 @@ + + + + + + + + external display - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

external display

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/external-display.html.gz b/en/tag/external-display.html.gz new file mode 100644 index 000000000..faab66aa1 Binary files /dev/null and b/en/tag/external-display.html.gz differ diff --git a/en/tag/filesreadallbytes.html b/en/tag/filesreadallbytes.html new file mode 100644 index 000000000..29d0a0fae --- /dev/null +++ b/en/tag/filesreadallbytes.html @@ -0,0 +1,296 @@ + + + + + + + + Files.readAllBytes - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Files.readAllBytes

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/filesreadallbytes.html.gz b/en/tag/filesreadallbytes.html.gz new file mode 100644 index 000000000..9610aea6a Binary files /dev/null and b/en/tag/filesreadallbytes.html.gz differ diff --git a/en/tag/firebase.html b/en/tag/firebase.html new file mode 100644 index 000000000..8ed71e8bd --- /dev/null +++ b/en/tag/firebase.html @@ -0,0 +1,296 @@ + + + + + + + + firebase - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

firebase

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/firebase.html.gz b/en/tag/firebase.html.gz new file mode 100644 index 000000000..30d1f1bf3 Binary files /dev/null and b/en/tag/firebase.html.gz differ diff --git a/en/tag/firefoxos.html b/en/tag/firefoxos.html new file mode 100644 index 000000000..b0af0002e --- /dev/null +++ b/en/tag/firefoxos.html @@ -0,0 +1,286 @@ + + + + + + + + FirefoxOS - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

FirefoxOS

+
+ +
+
    +
+
+
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/firefoxos.html.gz b/en/tag/firefoxos.html.gz new file mode 100644 index 000000000..f3a38bf77 Binary files /dev/null and b/en/tag/firefoxos.html.gz differ diff --git a/en/tag/flutter.html b/en/tag/flutter.html new file mode 100644 index 000000000..8b67ab241 --- /dev/null +++ b/en/tag/flutter.html @@ -0,0 +1,296 @@ + + + + + + + + flutter - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

flutter

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/flutter.html.gz b/en/tag/flutter.html.gz new file mode 100644 index 000000000..d1aad3435 Binary files /dev/null and b/en/tag/flutter.html.gz differ diff --git a/en/tag/getchild-item.html b/en/tag/getchild-item.html new file mode 100644 index 000000000..47044af13 --- /dev/null +++ b/en/tag/getchild-item.html @@ -0,0 +1,296 @@ + + + + + + + + GetChild-Item - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

GetChild-Item

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/getchild-item.html.gz b/en/tag/getchild-item.html.gz new file mode 100644 index 000000000..75cdb2276 Binary files /dev/null and b/en/tag/getchild-item.html.gz differ diff --git a/en/tag/git.html b/en/tag/git.html new file mode 100644 index 000000000..c54ee57b9 --- /dev/null +++ b/en/tag/git.html @@ -0,0 +1,296 @@ + + + + + + + + git - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

git

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/git.html.gz b/en/tag/git.html.gz new file mode 100644 index 000000000..92e82473d Binary files /dev/null and b/en/tag/git.html.gz differ diff --git a/en/tag/grepora.html b/en/tag/grepora.html new file mode 100644 index 000000000..e1efaf978 --- /dev/null +++ b/en/tag/grepora.html @@ -0,0 +1,296 @@ + + + + + + + + Grepora - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Grepora

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/grepora.html.gz b/en/tag/grepora.html.gz new file mode 100644 index 000000000..9261097ef Binary files /dev/null and b/en/tag/grepora.html.gz differ diff --git a/en/tag/hibernate.html b/en/tag/hibernate.html new file mode 100644 index 000000000..55cf0961d --- /dev/null +++ b/en/tag/hibernate.html @@ -0,0 +1,296 @@ + + + + + + + + Hibernate - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/hibernate.html.gz b/en/tag/hibernate.html.gz new file mode 100644 index 000000000..fd2164674 Binary files /dev/null and b/en/tag/hibernate.html.gz differ diff --git a/en/tag/hooks.html b/en/tag/hooks.html new file mode 100644 index 000000000..eb0e10cc1 --- /dev/null +++ b/en/tag/hooks.html @@ -0,0 +1,296 @@ + + + + + + + + hooks - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

hooks

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/hooks.html.gz b/en/tag/hooks.html.gz new file mode 100644 index 000000000..ff7c53dc1 Binary files /dev/null and b/en/tag/hooks.html.gz differ diff --git a/en/tag/html.html b/en/tag/html.html new file mode 100644 index 000000000..5c9d7d2e5 --- /dev/null +++ b/en/tag/html.html @@ -0,0 +1,286 @@ + + + + + + + + Html - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Html

+
+ +
+
    +
+
+
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/html.html.gz b/en/tag/html.html.gz new file mode 100644 index 000000000..2570f2a5f Binary files /dev/null and b/en/tag/html.html.gz differ diff --git a/en/tag/icmp-pinger-more-than-75.html b/en/tag/icmp-pinger-more-than-75.html new file mode 100644 index 000000000..2bc6f6f7c --- /dev/null +++ b/en/tag/icmp-pinger-more-than-75.html @@ -0,0 +1,296 @@ + + + + + + + + icmp pinger more than 75 - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

icmp pinger more than 75

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/icmp-pinger-more-than-75.html.gz b/en/tag/icmp-pinger-more-than-75.html.gz new file mode 100644 index 000000000..82e843400 Binary files /dev/null and b/en/tag/icmp-pinger-more-than-75.html.gz differ diff --git a/en/tag/icmp-pinger.html b/en/tag/icmp-pinger.html new file mode 100644 index 000000000..4c2e715e6 --- /dev/null +++ b/en/tag/icmp-pinger.html @@ -0,0 +1,296 @@ + + + + + + + + icmp pinger - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

icmp pinger

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/icmp-pinger.html.gz b/en/tag/icmp-pinger.html.gz new file mode 100644 index 000000000..211bb0c6b Binary files /dev/null and b/en/tag/icmp-pinger.html.gz differ diff --git a/en/tag/imagemin-pngquant.html b/en/tag/imagemin-pngquant.html new file mode 100644 index 000000000..b3ea0576f --- /dev/null +++ b/en/tag/imagemin-pngquant.html @@ -0,0 +1,306 @@ + + + + + + + + imagemin-pngquant - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/imagemin-pngquant.html.gz b/en/tag/imagemin-pngquant.html.gz new file mode 100644 index 000000000..ce997257c Binary files /dev/null and b/en/tag/imagemin-pngquant.html.gz differ diff --git a/en/tag/imagemin.html b/en/tag/imagemin.html new file mode 100644 index 000000000..44963f259 --- /dev/null +++ b/en/tag/imagemin.html @@ -0,0 +1,306 @@ + + + + + + + + imagemin - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/imagemin.html.gz b/en/tag/imagemin.html.gz new file mode 100644 index 000000000..f22916327 Binary files /dev/null and b/en/tag/imagemin.html.gz differ diff --git a/en/tag/java.html b/en/tag/java.html new file mode 100644 index 000000000..b3c895c3a --- /dev/null +++ b/en/tag/java.html @@ -0,0 +1,316 @@ + + + + + + + + Java - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/java.html.gz b/en/tag/java.html.gz new file mode 100644 index 000000000..111ec7242 Binary files /dev/null and b/en/tag/java.html.gz differ diff --git a/en/tag/javanetsocketexception.html b/en/tag/javanetsocketexception.html new file mode 100644 index 000000000..6220b18e2 --- /dev/null +++ b/en/tag/javanetsocketexception.html @@ -0,0 +1,296 @@ + + + + + + + + java.net.SocketException - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/javanetsocketexception.html.gz b/en/tag/javanetsocketexception.html.gz new file mode 100644 index 000000000..92c570ae5 Binary files /dev/null and b/en/tag/javanetsocketexception.html.gz differ diff --git a/en/tag/linux.html b/en/tag/linux.html new file mode 100644 index 000000000..7e2ff66a1 --- /dev/null +++ b/en/tag/linux.html @@ -0,0 +1,296 @@ + + + + + + + + Linux - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ + +
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/linux.html.gz b/en/tag/linux.html.gz new file mode 100644 index 000000000..7f925142b Binary files /dev/null and b/en/tag/linux.html.gz differ diff --git a/en/tag/low-memory.html b/en/tag/low-memory.html new file mode 100644 index 000000000..bce4812d1 --- /dev/null +++ b/en/tag/low-memory.html @@ -0,0 +1,296 @@ + + + + + + + + Low memory - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Low memory

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/low-memory.html.gz b/en/tag/low-memory.html.gz new file mode 100644 index 000000000..dc90b8675 Binary files /dev/null and b/en/tag/low-memory.html.gz differ diff --git a/en/tag/microservices.html b/en/tag/microservices.html new file mode 100644 index 000000000..b46c83694 --- /dev/null +++ b/en/tag/microservices.html @@ -0,0 +1,306 @@ + + + + + + + + microservices - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/microservices.html.gz b/en/tag/microservices.html.gz new file mode 100644 index 000000000..3ee4191b1 Binary files /dev/null and b/en/tag/microservices.html.gz differ diff --git a/en/tag/microsoft.html b/en/tag/microsoft.html new file mode 100644 index 000000000..7da70fc45 --- /dev/null +++ b/en/tag/microsoft.html @@ -0,0 +1,296 @@ + + + + + + + + Microsoft - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Microsoft

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/microsoft.html.gz b/en/tag/microsoft.html.gz new file mode 100644 index 000000000..0142e428c Binary files /dev/null and b/en/tag/microsoft.html.gz differ diff --git a/en/tag/monitor-website.html b/en/tag/monitor-website.html new file mode 100644 index 000000000..93830ebfe --- /dev/null +++ b/en/tag/monitor-website.html @@ -0,0 +1,296 @@ + + + + + + + + Monitor Website - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Monitor Website

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/monitor-website.html.gz b/en/tag/monitor-website.html.gz new file mode 100644 index 000000000..769f74d94 Binary files /dev/null and b/en/tag/monitor-website.html.gz differ diff --git a/en/tag/mysql-dual-password.html b/en/tag/mysql-dual-password.html new file mode 100644 index 000000000..aa418a5fa --- /dev/null +++ b/en/tag/mysql-dual-password.html @@ -0,0 +1,296 @@ + + + + + + + + MySQL Dual Password - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/mysql-dual-password.html.gz b/en/tag/mysql-dual-password.html.gz new file mode 100644 index 000000000..8ca970178 Binary files /dev/null and b/en/tag/mysql-dual-password.html.gz differ diff --git a/en/tag/mysql-replication.html b/en/tag/mysql-replication.html new file mode 100644 index 000000000..15c317db9 --- /dev/null +++ b/en/tag/mysql-replication.html @@ -0,0 +1,296 @@ + + + + + + + + MySQL Replication - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

MySQL Replication

+
+ + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/mysql-replication.html.gz b/en/tag/mysql-replication.html.gz new file mode 100644 index 000000000..d6d777528 Binary files /dev/null and b/en/tag/mysql-replication.html.gz differ diff --git a/en/tag/mysql-restart.html b/en/tag/mysql-restart.html new file mode 100644 index 000000000..87c38ea8f --- /dev/null +++ b/en/tag/mysql-restart.html @@ -0,0 +1,296 @@ + + + + + + + + MySQL Restart - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

MySQL Restart

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/mysql-restart.html.gz b/en/tag/mysql-restart.html.gz new file mode 100644 index 000000000..646822de1 Binary files /dev/null and b/en/tag/mysql-restart.html.gz differ diff --git a/en/tag/mysql.html b/en/tag/mysql.html new file mode 100644 index 000000000..68f460203 --- /dev/null +++ b/en/tag/mysql.html @@ -0,0 +1,326 @@ + + + + + + + + MySQL - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/mysql.html.gz b/en/tag/mysql.html.gz new file mode 100644 index 000000000..6436ad84a Binary files /dev/null and b/en/tag/mysql.html.gz differ diff --git a/en/tag/net.html b/en/tag/net.html new file mode 100644 index 000000000..b11cf0236 --- /dev/null +++ b/en/tag/net.html @@ -0,0 +1,296 @@ + + + + + + + + .net - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

.net

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/net.html.gz b/en/tag/net.html.gz new file mode 100644 index 000000000..0fdff094c Binary files /dev/null and b/en/tag/net.html.gz differ diff --git a/en/tag/noclassdeffound.html b/en/tag/noclassdeffound.html new file mode 100644 index 000000000..8b6a8dd5e --- /dev/null +++ b/en/tag/noclassdeffound.html @@ -0,0 +1,296 @@ + + + + + + + + NoClassDefFound - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

NoClassDefFound

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/noclassdeffound.html.gz b/en/tag/noclassdeffound.html.gz new file mode 100644 index 000000000..e6a0d0dbf Binary files /dev/null and b/en/tag/noclassdeffound.html.gz differ diff --git a/en/tag/node-js.html b/en/tag/node-js.html new file mode 100644 index 000000000..b80e5294d --- /dev/null +++ b/en/tag/node-js.html @@ -0,0 +1,306 @@ + + + + + + + + node js - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/node-js.html.gz b/en/tag/node-js.html.gz new file mode 100644 index 000000000..43719f17b Binary files /dev/null and b/en/tag/node-js.html.gz differ diff --git a/en/tag/nodejs.html b/en/tag/nodejs.html new file mode 100644 index 000000000..b46e8ac27 --- /dev/null +++ b/en/tag/nodejs.html @@ -0,0 +1,316 @@ + + + + + + + + nodejs - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/nodejs.html.gz b/en/tag/nodejs.html.gz new file mode 100644 index 000000000..c750ee4c8 Binary files /dev/null and b/en/tag/nodejs.html.gz differ diff --git a/en/tag/openssh.html b/en/tag/openssh.html new file mode 100644 index 000000000..a738d9651 --- /dev/null +++ b/en/tag/openssh.html @@ -0,0 +1,296 @@ + + + + + + + + openssh - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

openssh

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/openssh.html.gz b/en/tag/openssh.html.gz new file mode 100644 index 000000000..1eb9ca959 Binary files /dev/null and b/en/tag/openssh.html.gz differ diff --git a/en/tag/out-of-memory.html b/en/tag/out-of-memory.html new file mode 100644 index 000000000..5875044a4 --- /dev/null +++ b/en/tag/out-of-memory.html @@ -0,0 +1,296 @@ + + + + + + + + Out of memory - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Out of memory

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/out-of-memory.html.gz b/en/tag/out-of-memory.html.gz new file mode 100644 index 000000000..df6f75e12 Binary files /dev/null and b/en/tag/out-of-memory.html.gz differ diff --git a/en/tag/outofmemory.html b/en/tag/outofmemory.html new file mode 100644 index 000000000..8745319ee --- /dev/null +++ b/en/tag/outofmemory.html @@ -0,0 +1,296 @@ + + + + + + + + outOfMemory - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

outOfMemory

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/outofmemory.html.gz b/en/tag/outofmemory.html.gz new file mode 100644 index 000000000..fa1795b27 Binary files /dev/null and b/en/tag/outofmemory.html.gz differ diff --git a/en/tag/parcel.html b/en/tag/parcel.html new file mode 100644 index 000000000..33ec419a5 --- /dev/null +++ b/en/tag/parcel.html @@ -0,0 +1,296 @@ + + + + + + + + parcel - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ + +
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/parcel.html.gz b/en/tag/parcel.html.gz new file mode 100644 index 000000000..bef9e1860 Binary files /dev/null and b/en/tag/parcel.html.gz differ diff --git a/en/tag/poller-proccess-more-than-75.html b/en/tag/poller-proccess-more-than-75.html new file mode 100644 index 000000000..6cfcd6595 --- /dev/null +++ b/en/tag/poller-proccess-more-than-75.html @@ -0,0 +1,296 @@ + + + + + + + + Poller proccess more than 75% - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Poller proccess more than 75%

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/poller-proccess-more-than-75.html.gz b/en/tag/poller-proccess-more-than-75.html.gz new file mode 100644 index 000000000..550c65486 Binary files /dev/null and b/en/tag/poller-proccess-more-than-75.html.gz differ diff --git a/en/tag/powershell-mail.html b/en/tag/powershell-mail.html new file mode 100644 index 000000000..9b925004c --- /dev/null +++ b/en/tag/powershell-mail.html @@ -0,0 +1,296 @@ + + + + + + + + Powershell mail - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Powershell mail

+
+ + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/powershell-mail.html.gz b/en/tag/powershell-mail.html.gz new file mode 100644 index 000000000..48bc48e23 Binary files /dev/null and b/en/tag/powershell-mail.html.gz differ diff --git a/en/tag/powershell-monitoring.html b/en/tag/powershell-monitoring.html new file mode 100644 index 000000000..389160eb6 --- /dev/null +++ b/en/tag/powershell-monitoring.html @@ -0,0 +1,296 @@ + + + + + + + + Powershell monitoring - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Powershell monitoring

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/powershell-monitoring.html.gz b/en/tag/powershell-monitoring.html.gz new file mode 100644 index 000000000..f373f9992 Binary files /dev/null and b/en/tag/powershell-monitoring.html.gz differ diff --git a/en/tag/powershell.html b/en/tag/powershell.html new file mode 100644 index 000000000..945a1427f --- /dev/null +++ b/en/tag/powershell.html @@ -0,0 +1,306 @@ + + + + + + + + PowerShell - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/powershell.html.gz b/en/tag/powershell.html.gz new file mode 100644 index 000000000..34b6f695f Binary files /dev/null and b/en/tag/powershell.html.gz differ diff --git a/en/tag/pre-commit.html b/en/tag/pre-commit.html new file mode 100644 index 000000000..47aa392fe --- /dev/null +++ b/en/tag/pre-commit.html @@ -0,0 +1,296 @@ + + + + + + + + pre-commit - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

pre-commit

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/pre-commit.html.gz b/en/tag/pre-commit.html.gz new file mode 100644 index 000000000..d3821a8c5 Binary files /dev/null and b/en/tag/pre-commit.html.gz differ diff --git a/en/tag/protocol-family-unavailable.html b/en/tag/protocol-family-unavailable.html new file mode 100644 index 000000000..c01e389ad --- /dev/null +++ b/en/tag/protocol-family-unavailable.html @@ -0,0 +1,296 @@ + + + + + + + + Protocol family unavailable - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/protocol-family-unavailable.html.gz b/en/tag/protocol-family-unavailable.html.gz new file mode 100644 index 000000000..68e5fbfec Binary files /dev/null and b/en/tag/protocol-family-unavailable.html.gz differ diff --git a/en/tag/rabbitmq.html b/en/tag/rabbitmq.html new file mode 100644 index 000000000..aaff2c059 --- /dev/null +++ b/en/tag/rabbitmq.html @@ -0,0 +1,306 @@ + + + + + + + + rabbitmq - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/rabbitmq.html.gz b/en/tag/rabbitmq.html.gz new file mode 100644 index 000000000..589c752e2 Binary files /dev/null and b/en/tag/rabbitmq.html.gz differ diff --git a/en/tag/random.html b/en/tag/random.html new file mode 100644 index 000000000..3b483c821 --- /dev/null +++ b/en/tag/random.html @@ -0,0 +1,296 @@ + + + + + + + + Random - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Random

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/random.html.gz b/en/tag/random.html.gz new file mode 100644 index 000000000..cddbd215e Binary files /dev/null and b/en/tag/random.html.gz differ diff --git a/en/tag/raspberry.html b/en/tag/raspberry.html new file mode 100644 index 000000000..ea78b3b28 --- /dev/null +++ b/en/tag/raspberry.html @@ -0,0 +1,286 @@ + + + + + + + + raspberry - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

raspberry

+
+ +
+
    +
+
+
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/raspberry.html.gz b/en/tag/raspberry.html.gz new file mode 100644 index 000000000..3942c3047 Binary files /dev/null and b/en/tag/raspberry.html.gz differ diff --git a/en/tag/react.html b/en/tag/react.html new file mode 100644 index 000000000..403d190df --- /dev/null +++ b/en/tag/react.html @@ -0,0 +1,296 @@ + + + + + + + + react - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ + +
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/react.html.gz b/en/tag/react.html.gz new file mode 100644 index 000000000..c298c9704 Binary files /dev/null and b/en/tag/react.html.gz differ diff --git a/en/tag/remove-item.html b/en/tag/remove-item.html new file mode 100644 index 000000000..8057e63ba --- /dev/null +++ b/en/tag/remove-item.html @@ -0,0 +1,296 @@ + + + + + + + + Remove-Item - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Remove-Item

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/remove-item.html.gz b/en/tag/remove-item.html.gz new file mode 100644 index 000000000..0d8ab8621 Binary files /dev/null and b/en/tag/remove-item.html.gz differ diff --git a/en/tag/replacing-underscore.html b/en/tag/replacing-underscore.html new file mode 100644 index 000000000..b13500296 --- /dev/null +++ b/en/tag/replacing-underscore.html @@ -0,0 +1,296 @@ + + + + + + + + replacing underscore - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

replacing underscore

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/replacing-underscore.html.gz b/en/tag/replacing-underscore.html.gz new file mode 100644 index 000000000..fb74e2d92 Binary files /dev/null and b/en/tag/replacing-underscore.html.gz differ diff --git a/en/tag/resource-governor.html b/en/tag/resource-governor.html new file mode 100644 index 000000000..c2ff282f7 --- /dev/null +++ b/en/tag/resource-governor.html @@ -0,0 +1,296 @@ + + + + + + + + Resource Governor - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Resource Governor

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/resource-governor.html.gz b/en/tag/resource-governor.html.gz new file mode 100644 index 000000000..78e0b1f95 Binary files /dev/null and b/en/tag/resource-governor.html.gz differ diff --git a/en/tag/script.html b/en/tag/script.html new file mode 100644 index 000000000..f9173212b --- /dev/null +++ b/en/tag/script.html @@ -0,0 +1,296 @@ + + + + + + + + Script - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Script

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/script.html.gz b/en/tag/script.html.gz new file mode 100644 index 000000000..19f87131f Binary files /dev/null and b/en/tag/script.html.gz differ diff --git a/en/tag/shell.html b/en/tag/shell.html new file mode 100644 index 000000000..585a34fe7 --- /dev/null +++ b/en/tag/shell.html @@ -0,0 +1,326 @@ + + + + + + + + Shell - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/shell.html.gz b/en/tag/shell.html.gz new file mode 100644 index 000000000..7fe84f789 Binary files /dev/null and b/en/tag/shell.html.gz differ diff --git a/en/tag/specify-columns.html b/en/tag/specify-columns.html new file mode 100644 index 000000000..3873719b6 --- /dev/null +++ b/en/tag/specify-columns.html @@ -0,0 +1,296 @@ + + + + + + + + Specify columns - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Specify columns

+
+ + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/specify-columns.html.gz b/en/tag/specify-columns.html.gz new file mode 100644 index 000000000..64aa963b3 Binary files /dev/null and b/en/tag/specify-columns.html.gz differ diff --git a/en/tag/sqlserver.html b/en/tag/sqlserver.html new file mode 100644 index 000000000..9c89061d4 --- /dev/null +++ b/en/tag/sqlserver.html @@ -0,0 +1,316 @@ + + + + + + + + SQLServer - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/sqlserver.html.gz b/en/tag/sqlserver.html.gz new file mode 100644 index 000000000..09cf0717b Binary files /dev/null and b/en/tag/sqlserver.html.gz differ diff --git a/en/tag/ssh-tunnel.html b/en/tag/ssh-tunnel.html new file mode 100644 index 000000000..a94bc6d67 --- /dev/null +++ b/en/tag/ssh-tunnel.html @@ -0,0 +1,296 @@ + + + + + + + + ssh tunnel - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

ssh tunnel

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/ssh-tunnel.html.gz b/en/tag/ssh-tunnel.html.gz new file mode 100644 index 000000000..5f12c328d Binary files /dev/null and b/en/tag/ssh-tunnel.html.gz differ diff --git a/en/tag/ssh.html b/en/tag/ssh.html new file mode 100644 index 000000000..101cb9a52 --- /dev/null +++ b/en/tag/ssh.html @@ -0,0 +1,296 @@ + + + + + + + + ssh - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

ssh

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/ssh.html.gz b/en/tag/ssh.html.gz new file mode 100644 index 000000000..9b02e94df Binary files /dev/null and b/en/tag/ssh.html.gz differ diff --git a/en/tag/stop-proccess.html b/en/tag/stop-proccess.html new file mode 100644 index 000000000..949f91d62 --- /dev/null +++ b/en/tag/stop-proccess.html @@ -0,0 +1,296 @@ + + + + + + + + Stop-Proccess - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Stop-Proccess

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/stop-proccess.html.gz b/en/tag/stop-proccess.html.gz new file mode 100644 index 000000000..62f2abe71 Binary files /dev/null and b/en/tag/stop-proccess.html.gz differ diff --git a/en/tag/the-database-principal-owns-a-schema.html b/en/tag/the-database-principal-owns-a-schema.html new file mode 100644 index 000000000..54832f3c1 --- /dev/null +++ b/en/tag/the-database-principal-owns-a-schema.html @@ -0,0 +1,296 @@ + + + + + + + + The database principal owns a schema - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

The database principal owns a schema

+
+ + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/the-database-principal-owns-a-schema.html.gz b/en/tag/the-database-principal-owns-a-schema.html.gz new file mode 100644 index 000000000..2b6690a03 Binary files /dev/null and b/en/tag/the-database-principal-owns-a-schema.html.gz differ diff --git a/en/tag/through-firewall.html b/en/tag/through-firewall.html new file mode 100644 index 000000000..e1e06a8d8 --- /dev/null +++ b/en/tag/through-firewall.html @@ -0,0 +1,296 @@ + + + + + + + + through firewall - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

through firewall

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/through-firewall.html.gz b/en/tag/through-firewall.html.gz new file mode 100644 index 000000000..47bcdc3d0 Binary files /dev/null and b/en/tag/through-firewall.html.gz differ diff --git a/en/tag/time-schedule-blocking.html b/en/tag/time-schedule-blocking.html new file mode 100644 index 000000000..4bd20fcca --- /dev/null +++ b/en/tag/time-schedule-blocking.html @@ -0,0 +1,296 @@ + + + + + + + + Time Schedule blocking - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Time Schedule blocking

+
+ + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/time-schedule-blocking.html.gz b/en/tag/time-schedule-blocking.html.gz new file mode 100644 index 000000000..5673ae38d Binary files /dev/null and b/en/tag/time-schedule-blocking.html.gz differ diff --git a/en/tag/tools.html b/en/tag/tools.html new file mode 100644 index 000000000..259cfa8d2 --- /dev/null +++ b/en/tag/tools.html @@ -0,0 +1,286 @@ + + + + + + + + Tools - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Tools

+
+ +
+
    +
+
+
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/tools.html.gz b/en/tag/tools.html.gz new file mode 100644 index 000000000..48c019d09 Binary files /dev/null and b/en/tag/tools.html.gz differ diff --git a/en/tag/tunnel.html b/en/tag/tunnel.html new file mode 100644 index 000000000..b377f61d5 --- /dev/null +++ b/en/tag/tunnel.html @@ -0,0 +1,296 @@ + + + + + + + + tunnel - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

tunnel

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/tunnel.html.gz b/en/tag/tunnel.html.gz new file mode 100644 index 000000000..4f563ac20 Binary files /dev/null and b/en/tag/tunnel.html.gz differ diff --git a/en/tag/user.html b/en/tag/user.html new file mode 100644 index 000000000..8a5fc9df7 --- /dev/null +++ b/en/tag/user.html @@ -0,0 +1,306 @@ + + + + + + + + User - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/user.html.gz b/en/tag/user.html.gz new file mode 100644 index 000000000..6fa0cc891 Binary files /dev/null and b/en/tag/user.html.gz differ diff --git a/en/tag/wildfly.html b/en/tag/wildfly.html new file mode 100644 index 000000000..452a5ad8d --- /dev/null +++ b/en/tag/wildfly.html @@ -0,0 +1,296 @@ + + + + + + + + WildFly - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/wildfly.html.gz b/en/tag/wildfly.html.gz new file mode 100644 index 000000000..3f0ecad61 Binary files /dev/null and b/en/tag/wildfly.html.gz differ diff --git a/en/tag/yeoman.html b/en/tag/yeoman.html new file mode 100644 index 000000000..b3882c47c --- /dev/null +++ b/en/tag/yeoman.html @@ -0,0 +1,296 @@ + + + + + + + + yeoman - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ + +
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/yeoman.html.gz b/en/tag/yeoman.html.gz new file mode 100644 index 000000000..84244d2ef Binary files /dev/null and b/en/tag/yeoman.html.gz differ diff --git a/en/tag/zabbix-poller.html b/en/tag/zabbix-poller.html new file mode 100644 index 000000000..f5edab13c --- /dev/null +++ b/en/tag/zabbix-poller.html @@ -0,0 +1,296 @@ + + + + + + + + Zabbix Poller - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Zabbix Poller

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/zabbix-poller.html.gz b/en/tag/zabbix-poller.html.gz new file mode 100644 index 000000000..4a4d5a582 Binary files /dev/null and b/en/tag/zabbix-poller.html.gz differ diff --git a/en/tag/zabbix-server.html b/en/tag/zabbix-server.html new file mode 100644 index 000000000..63b8fe33f --- /dev/null +++ b/en/tag/zabbix-server.html @@ -0,0 +1,296 @@ + + + + + + + + Zabbix Server - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Zabbix Server

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/zabbix-server.html.gz b/en/tag/zabbix-server.html.gz new file mode 100644 index 000000000..666e8cb2f Binary files /dev/null and b/en/tag/zabbix-server.html.gz differ diff --git a/en/tag/zabbix.html b/en/tag/zabbix.html new file mode 100644 index 000000000..dcaaf78b7 --- /dev/null +++ b/en/tag/zabbix.html @@ -0,0 +1,326 @@ + + + + + + + + Zabbix - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tag/zabbix.html.gz b/en/tag/zabbix.html.gz new file mode 100644 index 000000000..fb3ba1a3e Binary files /dev/null and b/en/tag/zabbix.html.gz differ diff --git a/en/tags.html b/en/tags.html new file mode 100644 index 000000000..30b2db196 --- /dev/null +++ b/en/tags.html @@ -0,0 +1,381 @@ + + + + + + + + Sipmann - Tags + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/tags.html.gz b/en/tags.html.gz new file mode 100644 index 000000000..7e45ea97e Binary files /dev/null and b/en/tags.html.gz differ diff --git a/en/the-power-of-powershell.html b/en/the-power-of-powershell.html new file mode 100644 index 000000000..5b86d9f87 --- /dev/null +++ b/en/the-power-of-powershell.html @@ -0,0 +1,596 @@ + + + + + + + + The power of PowerShell - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

The power of PowerShell

+
+ +
+
+ +
+

As a long time Linux user, I've automated a few things with bash scripts and stayed away from PowerShell... I've moved to a Windows environment a few years ago and still, haven gave a shot to PS. But why not? I've made a few scripts to automate some tasks at a Protheus server.

+

I found the PS scripts being easy to read and understand. Bellow, we have a script to remove files filtering their extension (or no extension at all like the following script).

+
Get-ChildItem "C:\TOTVS\protheus_data\system" -File -Filter *. | Move-Item -Force -Destination { 
+    <# Diretory where the files will be moved. You can use Date formats to help name it #>
+    <# LastWriteTime proprtie from the current file #>
+    $dir = "C:\bad_files\{0:yyyy\\MM\\dd}" -f $_.LastWriteTime
+    $null = mkdir $dir -Force 
+    "$dir\$($_.Name)"
+}
+
+ +

Have you ever been in the need to remove files based on other file content? Bello a script where I read a file that has the names of files that I want to remove.

+
foreach($line in Get-Content .\Desktop\bad_files.txt) {
+    if (Test-Path('\\x.y.z.a\c$\TOTVS\protheus_data\xmls\'+$line+'.xml')) {
+        Remove-Item('\\x.y.z.a\c$\TOTVS\protheus_data\xmls\'+$line+'.xml')
+    } else {
+        echo $line + ' - File not found'
+    }
+}
+
+ +

And a bonus script to stop/start services (if you handle some Protheus Server, you know why I do that).

+
$servicesNames = 'app_main',
+    'app_worker1',
+    'app_worker2',
+    'app_worker3',
+    'app_worker4',
+    'app_worker5'
+
+Write-host "Stoping Services"
+Write-host "--------------------------"
+
+foreach ($srv in $servicesNames) {
+    Write-host "Stopping: " + $srv
+    $SrvPID = (get-wmiobject win32_service | where { $_.name -eq $srv}).processID
+    Write-host "PID: " + $SrvPID
+
+    <# Force if the proccess is stucked #>
+    Stop-Process $SrvPID -Force
+    Write-host "PDI " + $SrvPID + " stopped"
+}
+
+
+Write-host "Starting Services"
+Write-host "--------------------------"
+
+foreach ($srv in $servicesNames) {
+    Write-host "Starting: " + $srv
+    Start-Service $srv
+}
+
+ +

Do you have any automated script? Share with us :)

+
+ + +
+
+

Translations:

+ +
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/the-power-of-powershell.html.gz b/en/the-power-of-powershell.html.gz new file mode 100644 index 000000000..ddc763fd8 Binary files /dev/null and b/en/the-power-of-powershell.html.gz differ diff --git a/en/top_level_statement_csharp_9.html b/en/top_level_statement_csharp_9.html new file mode 100644 index 000000000..457b8d046 --- /dev/null +++ b/en/top_level_statement_csharp_9.html @@ -0,0 +1,514 @@ + + + + + + + + Top Level Statement in C# 9 - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Top Level Statement in C# 9

+
+ +
+
+ +
+

Hey folks, I'm coming along to tell you a few things about the new feature of C# 9. Every time you want to start a new project, you always have the same Main File, with the same structure. At the next version of C# (version 9), we'll have a new feature called Top Level Statement. With that, we'll be able to code our app without any namespace/class/public void static main structure. Take a look at the code below.

+
using System;
+
+Console.WriteLine("Hello World!");
+
+ +

It looks pretty simple, but with this, you can play around with your code, and even code a simple/tiny Web API. To start playing with the new features, firstly download the .net 5 SDK and change your .csproj file to target the .net 5 and language preview like bellow.

+
<Project Sdk="Microsoft.NET.Sdk">
+  <PropertyGroup>
+    <OutputType>Exe</OutputType>
+    <TargetFramework>net5.0</TargetFramework>
+    <LangVersion>preview</LangVersion>
+  </PropertyGroup>
+</Project>
+
+ +

And you're ready to play with the awesome features available in the preview. Let's code a way to get the image of the day from NASA API and print the Picture of the Day. No awesome code here, it's really a way to show how simple a simple call could be. After here, why not save the image in a file? Maybe send the file over telegram?

+
using System;
+using System.Net.Http;
+using System.Text.Json;
+
+var API = "https://api.nasa.gov/planetary/apod?hd=true&api_key=DEMO_KEY";
+var cli = new HttpClient();
+
+var response = await cli.GetAsync(API);
+var data = JsonSerializer.Deserialize<NasaApi>(await response.Content.ReadAsStringAsync());
+
+Console.WriteLine(data.Url);
+
+ +

That's it for today folks. Keep an eye open for the awesome features C# 9 will bring to us, there's plenty more features already available.

+
+ + +
+
+

Translations:

+ +
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/top_level_statement_csharp_9.html.gz b/en/top_level_statement_csharp_9.html.gz new file mode 100644 index 000000000..86b6fb12c Binary files /dev/null and b/en/top_level_statement_csharp_9.html.gz differ diff --git a/en/using_git_hooks_easy_your_life.html b/en/using_git_hooks_easy_your_life.html new file mode 100644 index 000000000..1786b7111 --- /dev/null +++ b/en/using_git_hooks_easy_your_life.html @@ -0,0 +1,516 @@ + + + + + + + + Using git hooks to easy your life - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Using git hooks to easy your life

+
+ +
+
+ +
+

Hey folks, it's been a time since my last post. In the meantime, I moved to another state, changed job, and started learning new kinds of stuff. Today I would like to share one thing that I usually do with my small git projects. Git has many cool features, git hooks were one of them. I'll talk about the pre-commit hook today.

+

Let's say that, for some reason, you don't have a CI tool/server running after every commit and you want to enforce that every developer runs the tests before every commit? Git pre-commit to the rescue. You can code the hooks with shell, ruby, python, and I could be wrong, but even PHP would work. pre-commit is a client-side hook (we have server side too) and he's located inside the .git/hooks folder. Let's jump to the code... Create a file called 'pre-commit' inside that folder with the following code.

+
#!/bin/bash
+npm test # assuming you're using it inside a nodeJS project
+
+

Don't forget to make the script executable!! Now break your test and try to commit. That's easy but can save you from breaking the tests at the main CI/Travis/Codeship/etc and being notified by email :). Why not even validate the lint of your project or check if the coverage doesn't fall? Does your team/company have a patter for commit messages? No problem, there is a hook called commit-msg that you can use to validate your message.

+

+
+ + +
+
+

Translations:

+
    +
+
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/using_git_hooks_easy_your_life.html.gz b/en/using_git_hooks_easy_your_life.html.gz new file mode 100644 index 000000000..cb77dd191 Binary files /dev/null and b/en/using_git_hooks_easy_your_life.html.gz differ diff --git a/en/zabbix-icmp-pinger-processes-more-than-75.html b/en/zabbix-icmp-pinger-processes-more-than-75.html new file mode 100644 index 000000000..1b499cf72 --- /dev/null +++ b/en/zabbix-icmp-pinger-processes-more-than-75.html @@ -0,0 +1,525 @@ + + + + + + + + Zabbix ICMP pinger processes more than 75% - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Zabbix ICMP pinger processes more than 75%

+
+ +
+
+ +
+

So your monitoring sytems have grown and your zabbix started loggin "Zabbix icmp pinger processes more than 75% busy" at the dashboard.

+

Dashboard do zabbix avisando sobre o erro

+

All you have to do is open your config file (/etc/zabbix/zabbix_server.conf) and find the a tag named StartPingers. It'll be commented by default. Uncomment it and set it's value to something like 3 or 4. It should solve your problem.

+
### Option: StartPingers
+#       Number of pre-forked instances of ICMP pingers.
+#
+# Mandatory: no
+# Range: 0-1000
+# Default:
+StartPingers=4
+
+ +

How many Pingers do I need?

+

Well, there is no exact answer to this. If you set it too high, you'll be wasting resources. The best way to solve, it's increasing them as soon as you notice the percentage growing.

+
+ + +
+
+

Translations:

+ +
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/zabbix-icmp-pinger-processes-more-than-75.html.gz b/en/zabbix-icmp-pinger-processes-more-than-75.html.gz new file mode 100644 index 000000000..e35c2eac4 Binary files /dev/null and b/en/zabbix-icmp-pinger-processes-more-than-75.html.gz differ diff --git a/en/zabbix-poller-processes-more-than-75.html b/en/zabbix-poller-processes-more-than-75.html new file mode 100644 index 000000000..83d0ea5b5 --- /dev/null +++ b/en/zabbix-poller-processes-more-than-75.html @@ -0,0 +1,566 @@ + + + + + + + + Zabbix poller processes more than 75% - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Zabbix poller processes more than 75%

+
+ +
+
+ +
+

Hey folks, this is the third post about tweaking the Zabbix configurations. All changes that I've suggested here were based on a Zabbix Server with 50+ hosts. Another thing that can happen to your server, it's the poller get overwhelmed by the amount of servers that need to be polled plus the ones that are not responding. Bellow two images where you can see the log and the graphic where you can see the usage percent.

+

Dashboard log about the poller processes

+

Graph showing the utilization percent of each collector

+

To solve, let's go back to the zabbix_server.conf file and find two variables, StartPollers and StartPollersUnreachable. Increase them as needed. There's no magic number, you must see what works for you. But keep in mind that the StartPollersUnreachable is responsible for that host that can't be "reached" (of course) and will hold your poller more time.

+
### Option: StartPollers
+#       Number of pre-forked instances of pollers.
+#
+# Mandatory: no
+# Range: 0-1000
+# Default:
+StartPollers=20
+
+#...
+
+### Option: StartPollersUnreachable
+#       Number of pre-forked instances of pollers for unreachable hosts (including IPMI and Java).
+#       At least one poller for unreachable hosts must be running if regular, IPMI or Java pollers
+#       are started.
+#
+# Mandatory: no
+# Range: 0-1000
+# Default:
+StartPollersUnreachable=5
+
+ +

After the change, restart the server and wait a few moments and take a look again at your dashboard. Bellow the effect that I've got.

+

Graph showing the new utilization percent of the processes after the changes

+
+ + +
+
+

Translations:

+ +
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/zabbix-poller-processes-more-than-75.html.gz b/en/zabbix-poller-processes-more-than-75.html.gz new file mode 100644 index 000000000..bb0603166 Binary files /dev/null and b/en/zabbix-poller-processes-more-than-75.html.gz differ diff --git a/en/zabbix-running-on-low-memory-mode.html b/en/zabbix-running-on-low-memory-mode.html new file mode 100644 index 000000000..8511d0dd8 --- /dev/null +++ b/en/zabbix-running-on-low-memory-mode.html @@ -0,0 +1,555 @@ + + + + + + + + Zabbix Running on Low Memory Mode - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Zabbix Running on Low Memory Mode

+
+ +
+
+ +
+

Hey folks, another Zabbix post today. This one it's about increasing the Zabbix Server Cache. It's pretty common (if you have the default settings only) get a warning about your Zabbix value cache running on low memory mode at your dashboard or logs.

+

Zabbix Dashboard warning about the memory problem +Zabbix Dashboard cache graph 70% used

+

To solve, go back to your Zabbix config file (zabbix_server.conf) and look for the tag CacheSize. Uncomment it and set to a value bigger than 8M (8M it's the default value). In my case, we set a cache of 100M. After the change, restart the service.

+
### Option: CacheSize
+#       Size of configuration cache, in bytes.
+#       Shared memory size for storing host, item and trigger data.
+#
+# Mandatory: no
+# Range: 128K-64G
+# Default:
+CacheSize=100M #uncomment this line
+
+ +

Zabbix Dashboard resolved memory problem

+

See ya folks.

+
+ + +
+
+

Translations:

+ +
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/zabbix-running-on-low-memory-mode.html.gz b/en/zabbix-running-on-low-memory-mode.html.gz new file mode 100644 index 000000000..9505389b2 Binary files /dev/null and b/en/zabbix-running-on-low-memory-mode.html.gz differ diff --git a/en/zabbix-server-out-of-memory-crash.html b/en/zabbix-server-out-of-memory-crash.html new file mode 100644 index 000000000..197040676 --- /dev/null +++ b/en/zabbix-server-out-of-memory-crash.html @@ -0,0 +1,547 @@ + + + + + + + + Zabbix Server Out of Memory - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Zabbix Server Out of Memory

+
+ +
+
+ +
+

Do you have a crashing Zabbix Server and looking through the log /var/log/zabbix/zabbix_server.log you see the following out of memory message?

+
__mem_malloc: skipped 0 asked 24 skip_min 18446744073709551615 skip_max 0
+[file:dbconfig.c,line:94] __zbx_mem_realloc(): out of memory (requested 16 bytes)
+[file:dbconfig.c,line:94] __zbx_mem_realloc(): please increase CacheSize configuration parameter
+
+ +

Besides the clear solution to the error, that's a common issue on servers that have a few monitoring items on it (servers, switches, firewalls, databases, etc...). To solve, go to your zabbix_server.conf and look for the CacheSize property and set it to a higher value. Its default should be 8M. At a customer that has somewhere between 4 servers, 7 firewalls/appliances, and a few other things, a 32M did the job, but you can set up to 8G.

+

See ya folks.

+
+ + +
+
+

Translations:

+ +
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/en/zabbix-server-out-of-memory-crash.html.gz b/en/zabbix-server-out-of-memory-crash.html.gz new file mode 100644 index 000000000..76a83b041 Binary files /dev/null and b/en/zabbix-server-out-of-memory-crash.html.gz differ diff --git a/feeds/all-en.atom.xml b/feeds/all-en.atom.xml new file mode 100644 index 000000000..f24e0613f --- /dev/null +++ b/feeds/all-en.atom.xml @@ -0,0 +1,813 @@ + +Sipmannhttps://www.sipmann.com/2020-12-21T13:30:00-03:00Monitoring MySQL restarts with PowerShell2020-12-21T13:30:00-03:002020-12-21T13:30:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-12-21:/monitoring-mysql-restarts-with-powershell.html<p>Hey folks, it's time for another PowerShell script. If you haven't seen the other ones, check the links below.</p> +<ul> +<li><a href="https://www.sipmann.com/en/monitoring-mysql-replication-with-powershell.html">Monitoring MySQL replication with PowerShell</a></li> +</ul> +<p>Well, this one it's a pretty simple script, but again, if your customer doesn't have a Zabbix server or doesn't allow you to setup one to …</p><p>Hey folks, it's time for another PowerShell script. If you haven't seen the other ones, check the links below.</p> +<ul> +<li><a href="https://www.sipmann.com/en/monitoring-mysql-replication-with-powershell.html">Monitoring MySQL replication with PowerShell</a></li> +</ul> +<p>Well, this one it's a pretty simple script, but again, if your customer doesn't have a Zabbix server or doesn't allow you to setup one to do the monitoring, a set of scripts can be handy. We start executing some basic query <code>SHOW GLOBAL STATUS LIKE 'Uptime'</code>, with that we'll get exactly what we're looking for.</p> +<p>If for some reason, the command fails (watch for the "global" variable called <code>$lastExitCode</code>), we send an e-mail telling you about that connection problem.</p> +<p>And then, we get to the part where we parse the value, this one is pretty similar to the parse we did on the first post about using PowerShell to monitor MySQL. But we basically look for the Value line, split it by space and then parse the second position to an integer. And then all we have to do is check if the uptime is lower than our threshold, if it is we send an e-mail.</p> +<div class="highlight"><pre><span></span><code><span class="nv">$MailFrom</span> <span class="p">=</span> <span class="s1">&#39;maurio[at]sipmann.com&#39;</span> +<span class="nv">$MailTo</span> <span class="p">=</span> <span class="s1">&#39;mauricio[at]sipmann.com&#39;</span> +<span class="nv">$MysqlHost</span> <span class="p">=</span> <span class="s1">&#39;127.0.0.1&#39;</span> +<span class="nv">$MysqlUser</span> <span class="p">=</span> <span class="s1">&#39;root&#39;</span> +<span class="nv">$MysqlPass</span> <span class="p">=</span> <span class="s1">&#39;123&#39;</span> + + +<span class="nv">$data</span> <span class="p">=</span> <span class="p">$(</span><span class="n">mysql</span> <span class="n">-h</span> <span class="nv">$MysqlHost</span> <span class="n">-u</span> <span class="nv">$MysqlUser</span> <span class="n">-p</span><span class="s2">&quot;$MysqlPass&quot;</span> <span class="n">-e</span> <span class="s2">&quot;SHOW GLOBAL STATUS LIKE &#39;Uptime&#39; \G&quot;</span><span class="p">)</span> + +<span class="cm">&lt;# Unable to execute the sql Command #&gt;</span> +<span class="k">if</span> <span class="p">(</span><span class="nv">$lastExitCode</span> <span class="o">-eq</span> <span class="n">1</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Send-MailMessage</span> <span class="n">-To</span> <span class="nv">$MailTo</span> <span class="n">-From</span> <span class="nv">$MailFrom</span> <span class="n">-Subject</span> <span class="s1">&#39;Connection problem&#39;</span> <span class="n">-bodyAsHtml</span> <span class="s2">&quot;Connection problem on host ${MysqlHost}&quot;</span> <span class="n">-Credential</span> <span class="nb">Get-Credential</span> <span class="n">-SmtpServer</span> <span class="s1">&#39;smtp.office365.com&#39;</span> <span class="n">-Port</span> <span class="n">587</span> <span class="n">-UseSsl</span> + <span class="n">exit</span> +<span class="p">}</span> + +<span class="nv">$UpTime</span> <span class="p">=</span> <span class="no">[int]</span><span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Value:&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> + +<span class="cm">&lt;# If the uptime is lower then 20 minutes #&gt;</span> +<span class="k">if</span> <span class="p">(</span><span class="nv">$UpTime</span> <span class="o">-lt</span> <span class="n">1200</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Send-MailMessage</span> <span class="n">-To</span> <span class="nv">$MailTo</span> <span class="n">-From</span> <span class="nv">$MailFrom</span> <span class="n">-Subject</span> <span class="s2">&quot;MySQL Restarted&quot;</span> <span class="n">-bodyAsHtml</span> <span class="s2">&quot;MySQL host ${MysqlHost} restarted less than 20 minutes ago&quot;</span> <span class="n">-Credential</span> <span class="nb">Get-Credential</span> <span class="n">-SmtpServer</span> <span class="s1">&#39;smtp.office365.com&#39;</span> <span class="n">-Port</span> <span class="n">587</span> <span class="n">-UseSsl</span> +<span class="p">}</span> +</code></pre></div> + +<p>This script (and the other ones I use) is available at my GitHub <a href="https://github.com/sipmann/PowerShellScripts">here</a>. Keep in mind that the ones on the GitHub repo, are a little different from here.</p>Changing a MySQL user password across multiple application instances without downtime2020-12-09T13:40:00-03:002020-12-09T13:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-12-09:/mysql-dual-password-functionality.html<p>Do you need to change the password of a MySQL user that it's being used in an application, and can't allow a single downtime? Well, MySQL 8.0.14 came with a feature called <a href="https://dev.mysql.com/doc/refman/8.0/en/password-management.html#dual-passwords">Dual Password Support</a>, with it you can change the password keeping the previous password as a …</p><p>Do you need to change the password of a MySQL user that it's being used in an application, and can't allow a single downtime? Well, MySQL 8.0.14 came with a feature called <a href="https://dev.mysql.com/doc/refman/8.0/en/password-management.html#dual-passwords">Dual Password Support</a>, with it you can change the password keeping the previous password as a kind of backup. That way you still can log in using the old password or can start using the new one. With that, the password change workflow it's the following.</p> +<p>1) Change password keeping the old one;</p> +<p>2) Deploy the new config to your app/cluster;</p> +<p>3) Discard the old password.</p> +<p>To change the password and keep the old one, you have the following command.</p> +<div class="highlight"><pre><span></span><code><span class="k">ALTER</span> <span class="n">USER</span> <span class="s1">&#39;appuser&#39;</span><span class="o">@</span><span class="s1">&#39;localhost&#39;</span> <span class="n">IDENTIFIED</span> <span class="k">BY</span> <span class="s1">&#39;new_password&#39;</span> <span class="n">RETAIN</span> <span class="n">CURRENT</span> <span class="n">PASSWORD</span><span class="p">;</span> +</code></pre></div> + +<p>To discard the old one, run the following.</p> +<div class="highlight"><pre><span></span><code><span class="k">ALTER</span> <span class="n">USER</span> <span class="s1">&#39;appuser&#39;</span><span class="o">@</span><span class="s1">&#39;localhost&#39;</span> <span class="n">DISCARD</span> <span class="n">OLD</span> <span class="n">PASSWORD</span><span class="p">;</span> +</code></pre></div> + +<p>And you are done. Hope you find it as useful as I :)</p>Apache Nifi JSON to SQL Replacing underscore2020-12-02T14:00:00-03:002020-12-02T14:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-12-02:/apache-nifi-json-to-sql-replacing-underscore.html<p>Recently I was doing some ETL with Apache NiFi. But after a few minutes of drawing my flow, I saw that the component ConvertJSONToSQL was replacing the underscore ('_') from the field name in the where condition (I was preparing an Update SQL). That was weird because, at the set …</p><p>Recently I was doing some ETL with Apache NiFi. But after a few minutes of drawing my flow, I saw that the component ConvertJSONToSQL was replacing the underscore ('_') from the field name in the where condition (I was preparing an Update SQL). That was weird because, at the set statement, the field name was kept intact. After some research, I found that the property (see bellow) <code>Translate Field Names</code> was responsible for that weird replacement.</p> +<p><img alt="Apache NiFi JSONToSQL config" src="/images/apache_nifi_jsontosql.png"></p> +<p>Before setting it to <strong>FALSE</strong>, be aware that the properties on your JSON data must match exactly the name of your fields.</p>Blocking a user on SQL Server based on a schedule2020-11-14T07:00:00-03:002020-11-14T07:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-11-14:/blocking-user-on-sql-server-based-on-schedule.html<p>Ok, some time ago, I've posted about how you can set limits to connections on SQL Server using the <a href="https://www.sipmann.com/limiting-connection-resources-sql-server.html#.X6Cz8IhKhPY">Resource Governor</a>. But what if you can't use it? You always can block logins using a login trigger, but I don't like the idea of having selects running on every login …</p><p>Ok, some time ago, I've posted about how you can set limits to connections on SQL Server using the <a href="https://www.sipmann.com/limiting-connection-resources-sql-server.html#.X6Cz8IhKhPY">Resource Governor</a>. But what if you can't use it? You always can block logins using a login trigger, but I don't like the idea of having selects running on every login. So I came across with a solution using a stored procedure, a table and the Agent.</p> +<p>The main idea is, store the time that a user must be blocked and using the Agent, disable or enable the user. Bellow you can see the table (the table is in Portuguese, but I have a few comment blocks to help you).</p> +<div class="highlight"><pre><span></span><code><span class="k">CREATE</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"> </span><span class="p">(</span><span class="w"></span> +<span class="w"> </span><span class="n">Id</span><span class="w"> </span><span class="nc">INT</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">LoginName</span><span class="w"> </span><span class="nc">NVARCHAR</span><span class="p">(</span><span class="mi">100</span><span class="p">)</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">HrInicio</span><span class="w"> </span><span class="nc">TIME</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"> </span><span class="cm">/* Startint block time */</span><span class="w"></span> +<span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="nc">TIME</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"> </span><span class="cm">/* Ending block time */</span><span class="w"></span> +<span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="nc">INT</span><span class="w"> </span><span class="k">DEFAULT</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="cm">/* 0 = unblocked, 1 = blocked */</span><span class="w"></span> +<span class="w"> </span><span class="k">PRIMARY</span><span class="w"> </span><span class="k">KEY</span><span class="w"> </span><span class="p">(</span><span class="n">Id</span><span class="p">)</span><span class="w"></span> +<span class="p">);</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> + +<span class="cm">/* Don&#39;t block the SA user, precautions, you know */</span><span class="w"></span> +<span class="k">ALTER</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"></span> +<span class="w"> </span><span class="k">ADD</span><span class="w"> </span><span class="k">CONSTRAINT</span><span class="w"> </span><span class="n">chk_users</span><span class="w"> </span><span class="k">CHECK</span><span class="w"> </span><span class="p">(</span><span class="n">LoginName</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;sa&#39;</span><span class="p">));</span><span class="w"></span> + +<span class="k">ALTER</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"></span> +<span class="w"> </span><span class="k">ADD</span><span class="w"> </span><span class="k">CONSTRAINT</span><span class="w"> </span><span class="n">chk_hora_final_maior</span><span class="w"> </span><span class="k">CHECK</span><span class="w"> </span><span class="p">(</span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="n">HrInicio</span><span class="p">);</span><span class="w"></span> + +<span class="k">ALTER</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"></span> +<span class="w"> </span><span class="k">ADD</span><span class="w"> </span><span class="k">CONSTRAINT</span><span class="w"> </span><span class="n">chk_status_bloqueio</span><span class="w"> </span><span class="k">CHECK</span><span class="w"> </span><span class="p">(</span><span class="n">Bloqueado</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">));</span><span class="w"></span> + +<span class="k">CREATE</span><span class="w"> </span><span class="k">SEQUENCE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">seq_HorariosBloqueio</span><span class="w"> </span><span class="k">START</span><span class="w"> </span><span class="k">WITH</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="n">INCREMENT</span><span class="w"> </span><span class="k">BY</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +</code></pre></div> + +<p>After creating the table, let's check the procedure that will handle the enabling/disabling the users. Be aware that on the procedure, I've set the database name where the table was stored, you can change it replacing the <code>DBATOOLS</code> text to the database name where you created the table.</p> +<div class="highlight"><pre><span></span><code><span class="k">IF</span><span class="w"> </span><span class="nf">OBJECT_ID</span><span class="p">(</span><span class="s1">&#39;dbo.sp_ValidarLogin&#39;</span><span class="p">)</span><span class="w"> </span><span class="k">IS</span><span class="w"> </span><span class="k">NULL</span><span class="w"></span> +<span class="w"> </span><span class="k">EXEC</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;CREATE PROCEDURE dbo.sp_ValidarLogin AS RETURN 0;&#39;</span><span class="p">);</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> + +<span class="k">CREATE</span><span class="w"> </span><span class="ow">OR</span><span class="w"> </span><span class="k">ALTER</span><span class="w"> </span><span class="k">PROC</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">sp_ValidarLogin</span><span class="w"></span> +<span class="k">AS</span><span class="w"> </span><span class="k">BEGIN</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="nc">NVARCHAR</span><span class="p">(</span><span class="mi">100</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="nc">TIME</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="k">SET</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nf">CAST</span><span class="p">(</span><span class="nf">GETDATE</span><span class="p">()</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="nc">TIME</span><span class="p">);</span><span class="w"></span> + +<span class="w"> </span><span class="cm">/* Block the ones that aren&#39;t blocked already and maches the time */</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="n">block_cursor</span><span class="w"> </span><span class="nc">CURSOR</span><span class="w"></span> +<span class="w"> </span><span class="k">FOR</span><span class="w"> </span><span class="k">SELECT</span><span class="w"> </span><span class="n">LoginName</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&lt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&gt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"></span> +<span class="w"> </span><span class="k">OPEN</span><span class="w"> </span><span class="n">block_cursor</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">block_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> + +<span class="w"> </span><span class="k">WHILE</span><span class="w"> </span><span class="nb">@@FETCH_STATUS</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"></span> +<span class="w"> </span><span class="k">BEGIN</span><span class="w"></span> +<span class="w"> </span><span class="k">exec</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;ALTER LOGIN &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="s1">&#39; DISABLE;&#39;</span><span class="p">);</span><span class="w"></span> + +<span class="w"> </span><span class="k">print</span><span class="w"> </span><span class="s1">&#39;Bloqued usuario &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">block_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> +<span class="w"> </span><span class="k">END</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">CLOSE</span><span class="w"> </span><span class="n">block_cursor</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="k">DEALLOCATE</span><span class="w"> </span><span class="n">block_cursor</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">UPDATE</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">SET</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&lt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&gt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"></span> + + +<span class="w"> </span><span class="cm">/* Enable up who was blocked */</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="nc">CURSOR</span><span class="w"></span> +<span class="w"> </span><span class="k">FOR</span><span class="w"> </span><span class="k">SELECT</span><span class="w"> </span><span class="n">LoginName</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="p">(</span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">OR</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="p">)</span><span class="w"></span> +<span class="w"> </span><span class="k">OPEN</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> + +<span class="w"> </span><span class="k">WHILE</span><span class="w"> </span><span class="nb">@@FETCH_STATUS</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"></span> +<span class="w"> </span><span class="k">BEGIN</span><span class="w"></span> +<span class="w"> </span><span class="k">exec</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;ALTER LOGIN &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"> </span><span class="o">+</span><span class="s1">&#39; ENABLE;&#39;</span><span class="p">);</span><span class="w"></span> + +<span class="w"> </span><span class="k">print</span><span class="w"> </span><span class="s1">&#39;Unbloqued usuario &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> +<span class="w"> </span><span class="k">END</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">CLOSE</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="k">DEALLOCATE</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">UPDATE</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">SET</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="p">(</span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">OR</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="p">)</span><span class="w"></span> +<span class="k">END</span><span class="p">;</span><span class="w"></span> +</code></pre></div> + +<p>Ok, so now all you have to do, is schedule a job to run that stored procedure from minute to minute. Again, the main idea is tell the procedure when a user must be blocked and when it'll be unblocked. </p> +<div class="highlight"><pre><span></span><code><span class="err"> -- Will block the user protheus from 10 AM till 15 PM</span> +<span class="err"> INSERT INTO dbo.HorariosBloqueio (Id, LoginName, HrInicio, HrTermino) VALUES (NEXT VALUE FOR seq_HorariosBloqueio, &#39;protheus&#39;, &#39;10:00:00&#39;, &#39;15:00:00&#39;);</span> +</code></pre></div>How to set columns on select using Entity Framework2020-10-28T19:00:00-03:002020-10-28T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-28:/select_specific_fields_with_efcore.html<p>So, you use Entity Framework Core, and you usually code your selects like the following, maybe you are getting too much data.</p> +<div class="highlight"><pre><span></span><code><span class="kt">var</span> <span class="n">products</span> <span class="p">=</span> <span class="n">Products</span> + <span class="p">.</span><span class="n">Where</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span> <span class="p">&gt;</span> <span class="m">0</span><span class="p">)</span> + <span class="p">.</span><span class="n">OrderBy</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">)</span> + <span class="p">.</span><span class="n">ToList</span><span class="p">()</span> +</code></pre></div> + +<p>Running the query above, on my table, you'll get the following output, take a look …</p><p>So, you use Entity Framework Core, and you usually code your selects like the following, maybe you are getting too much data.</p> +<div class="highlight"><pre><span></span><code><span class="kt">var</span> <span class="n">products</span> <span class="p">=</span> <span class="n">Products</span> + <span class="p">.</span><span class="n">Where</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span> <span class="p">&gt;</span> <span class="m">0</span><span class="p">)</span> + <span class="p">.</span><span class="n">OrderBy</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">)</span> + <span class="p">.</span><span class="n">ToList</span><span class="p">()</span> +</code></pre></div> + +<p>Running the query above, on my table, you'll get the following output, take a look at how many columns you are getting back from your database.</p> +<p><img alt="Screenshot with every single column" src="/images/ef_core_allcolumns.png"></p> +<p>In my case, I only care about the Title, PublishedData, and a small description. So to get back only these fields, we have a few options. In the first one, we'll set the fields and return them as a dynamic object, the second one, is to give the .NET a class to use. </p> +<div class="highlight"><pre><span></span><code><span class="kt">var</span> <span class="n">products</span> <span class="p">=</span> <span class="n">Products</span> + + <span class="p">.</span><span class="n">Select</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="k">new</span> <span class="p">{</span><span class="n">p</span><span class="p">.</span><span class="n">ProductID</span><span class="p">,</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">,</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span><span class="p">,</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitPrice</span><span class="p">})</span> + <span class="c1">//.Select(p =&gt; new ProductDTO {p.ProductID, p.ProductName, p.UnitsInStock, p.UnitPrice})</span> + + <span class="p">.</span><span class="n">Where</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span> <span class="p">&gt;</span> <span class="m">0</span><span class="p">)</span> + <span class="p">.</span><span class="n">OrderBy</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">)</span> + <span class="p">.</span><span class="n">ToList</span><span class="p">()</span> +</code></pre></div> + +<p><img alt="Screenshot with fewer columns and also fewer data size" src="/images/ef_core_less_columns.png"></p>Zabbix Running on Low Memory Mode2020-10-20T19:00:00-03:002020-10-20T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-20:/zabbix-running-on-low-memory-mode.html<p>Hey folks, another Zabbix post today. This one it's about increasing the Zabbix Server Cache. It's pretty common (if you have the default settings only) get a warning about your <code>Zabbix value cache running on low memory mode</code> at your dashboard or logs.</p> +<p><img alt="Zabbix Dashboard warning about the memory problem" src="/images/zabbix_low_memory_mode.png"> +<img alt="Zabbix Dashboard cache graph 70% used" src="/images/zabbix_cache_filling.png"></p> +<p>To solve, go back to your Zabbix …</p><p>Hey folks, another Zabbix post today. This one it's about increasing the Zabbix Server Cache. It's pretty common (if you have the default settings only) get a warning about your <code>Zabbix value cache running on low memory mode</code> at your dashboard or logs.</p> +<p><img alt="Zabbix Dashboard warning about the memory problem" src="/images/zabbix_low_memory_mode.png"> +<img alt="Zabbix Dashboard cache graph 70% used" src="/images/zabbix_cache_filling.png"></p> +<p>To solve, go back to your Zabbix config file (<code>zabbix_server.conf</code>) and look for the tag <em>CacheSize</em>. Uncomment it and set to a value bigger than 8M (8M it's the default value). In my case, we set a cache of 100M. After the change, restart the service.</p> +<div class="highlight"><pre><span></span><code><span class="c1">### Option: CacheSize</span> +<span class="c1"># Size of configuration cache, in bytes.</span> +<span class="c1"># Shared memory size for storing host, item and trigger data.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 128K-64G</span> +<span class="c1"># Default:</span> +<span class="na">CacheSize</span><span class="o">=</span><span class="s">100M #uncomment this line</span> +</code></pre></div> + +<p><img alt="Zabbix Dashboard resolved memory problem" src="/images/zabbix_low_memory_solved.png"></p> +<p>See ya folks.</p>Monitoring MySQL Replication Status with PowerShell2020-10-14T19:00:00-03:002020-10-14T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-14:/monitoring-mysql-replication-with-powershell.html<p>I've been migration some bash scripts that I have to PowerShell, and it's time to migrate a script that monitors the replication of a MySQL database. The credit for the original script goes to <a href="https://handyman.dulare.com/mysql-replication-status-alerts-with-bash-script/">Paweł</a>. It's a simple script where I seek a few tags/fields that we get from …</p><p>I've been migration some bash scripts that I have to PowerShell, and it's time to migrate a script that monitors the replication of a MySQL database. The credit for the original script goes to <a href="https://handyman.dulare.com/mysql-replication-status-alerts-with-bash-script/">Paweł</a>. It's a simple script where I seek a few tags/fields that we get from <code>SHOW SLAVE STATUS\G</code> command, the fields are. <code>Slave_IO_Running</code>, <code>Slave_SQL_Running</code>, and <code>Seconds_Behind_Master</code>. I still need to figure out the proper way to store/read variables like usernames and passwords, if you have any tips, feel free to even make a pull request (<a href="https://github.com/sipmann/PowerShellScripts">here</a>) at the git where I'll store some scripts.</p> +<div class="highlight"><pre><span></span><code><span class="cm">&lt;#</span> +<span class="cm"> Variables definition</span> +<span class="cm">#&gt;</span> +<span class="nv">$MaxSeconds</span> <span class="p">=</span> <span class="n">120</span> <span class="c"># Max seconds behind master allowed</span> +<span class="nv">$MysqlUser</span> <span class="p">=</span> <span class="s1">&#39;root&#39;</span> +<span class="nv">$MysqlPass</span> <span class="p">=</span> <span class="s1">&#39;&#39;</span> + +<span class="nv">$MailTo</span> <span class="p">=</span> <span class="s1">&#39;mauricio@sipmann.com&#39;</span> +<span class="nv">$MailFrom</span> <span class="p">=</span> <span class="s1">&#39;mauricio@sipmann.com&#39;</span> + + +<span class="nv">$data</span> <span class="p">=</span> <span class="p">$(</span><span class="n">mysql</span> <span class="n">-u</span> <span class="nv">$MysqlUser</span> <span class="n">-p</span><span class="s2">&quot;$MysqlPass&quot;</span> <span class="n">-e</span> <span class="s1">&#39;SHOW SLAVE STATUS \G&#39;</span><span class="p">)</span> + +<span class="c">#Debug data</span> +<span class="c">#$data = Get-Content &#39;c:\temp\sampleresult.txt&#39;</span> + +<span class="cm">&lt;# Parse the data #&gt;</span> +<span class="nv">$IORunning</span> <span class="p">=</span> <span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Slave_IO_Running:&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> +<span class="nv">$SQLRunning</span> <span class="p">=</span> <span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Slave_SQL_Running:&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> +<span class="nv">$LastErrNo</span> <span class="p">=</span> <span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Last_Errno&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> +<span class="nv">$SecondsBh</span> <span class="p">=</span> <span class="no">[int]</span><span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Seconds_Behind_Master&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> + +<span class="k">If</span> <span class="p">(</span><span class="nv">$IORunning</span> <span class="o">-Eq</span> <span class="s1">&#39;No&#39;</span> <span class="o">-Or</span> <span class="nv">$SQLRunning</span> <span class="o">-Eq</span> <span class="s1">&#39;No&#39;</span> <span class="o">-Or</span> <span class="nv">$SecondsBh</span> <span class="o">-gt</span> <span class="nv">$MaxSeconds</span><span class="p">)</span> <span class="p">{</span> + <span class="nv">$MailBody</span> <span class="p">=</span> <span class="s1">&#39;&lt;h1&gt;Problema na replicação&lt;/h1&gt;&lt;br&gt;&#39;</span> + + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39; IO Running: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$IORunning</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39; SQL Running: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$SQLRunning</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39;Seconds Behind: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$SecondsBh</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39; Last Err No: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$LastErrNo</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + + <span class="cm">&lt;# Send e-mail, maybe some telegram message here too #&gt;</span> + <span class="nb">Send-MailMessage</span> <span class="n">-To</span> <span class="nv">$MailTo</span> <span class="n">-From</span> <span class="nv">$MailFrom</span> <span class="n">-Subject</span> <span class="s1">&#39;Problemas na replicação&#39;</span> <span class="n">-bodyAsHtml</span> <span class="nv">$MailBody</span> <span class="n">-Credential</span> <span class="p">(</span><span class="nb">Get-Credential</span><span class="p">)</span> <span class="n">-SmtpServer</span> <span class="s1">&#39;smtp.office365.com&#39;</span> <span class="n">-Port</span> <span class="n">587</span> <span class="n">-UseSsl</span> +<span class="p">}</span> <span class="k">Else</span> <span class="p">{</span> + <span class="nb">Write-Host</span> <span class="s2">&quot;Up and running&quot;</span> +<span class="p">}</span> +</code></pre></div>Microsoft Against Covid2020-10-03T19:00:00-03:002020-10-03T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-03:/microsoft-against-covid.html<p>Has your job been affected by covid? Well, last week I've posted on <a href="https://grepora.com/2020/09/17/microsoft-ignite-certification-voucher/">Grepora</a> about a Free Certification Voucher that Microsoft was giving away at the Microsoft Ignite event. After that, I found that they were also giving a huge discount to people who have had their job affected by …</p><p>Has your job been affected by covid? Well, last week I've posted on <a href="https://grepora.com/2020/09/17/microsoft-ignite-certification-voucher/">Grepora</a> about a Free Certification Voucher that Microsoft was giving away at the Microsoft Ignite event. After that, I found that they were also giving a huge discount to people who have had their job affected by covid pandemic. </p> +<p>To see more details about if you were eligible, access <a href="https://docs.microsoft.com/en-us/learn/certifications/skillingoffer">https://docs.microsoft.com/en-us/learn/certifications/skillingoffer</a>.</p>The power of PowerShell2020-09-21T19:00:00-03:002020-09-21T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-09-21:/the-power-of-powershell.html<p>As a long time Linux user, I've automated a few things with bash scripts and stayed away from PowerShell... I've moved to a Windows environment a few years ago and still, haven gave a shot to PS. But why not? I've made a few scripts to automate some tasks at …</p><p>As a long time Linux user, I've automated a few things with bash scripts and stayed away from PowerShell... I've moved to a Windows environment a few years ago and still, haven gave a shot to PS. But why not? I've made a few scripts to automate some tasks at a Protheus server.</p> +<p>I found the PS scripts being easy to read and understand. Bellow, we have a script to remove files filtering their extension (or no extension at all like the following script). </p> +<div class="highlight"><pre><span></span><code><span class="nb">Get-ChildItem</span> <span class="s2">&quot;C:\TOTVS\protheus_data\system&quot;</span> <span class="o">-File</span> <span class="n">-Filter</span> <span class="p">*.</span> <span class="p">|</span> <span class="nb">Move-Item</span> <span class="n">-Force</span> <span class="n">-Destination</span> <span class="p">{</span> + <span class="cm">&lt;# Diretory where the files will be moved. You can use Date formats to help name it #&gt;</span> + <span class="cm">&lt;# LastWriteTime proprtie from the current file #&gt;</span> + <span class="nv">$dir</span> <span class="p">=</span> <span class="s2">&quot;C:\bad_files\{0:yyyy\\MM\\dd}&quot;</span> <span class="o">-f</span> <span class="nv">$_</span><span class="p">.</span><span class="n">LastWriteTime</span> + <span class="nv">$null</span> <span class="p">=</span> <span class="n">mkdir</span> <span class="nv">$dir</span> <span class="n">-Force</span> + <span class="s2">&quot;$dir\</span><span class="p">$(</span><span class="nv">$_</span><span class="p">.</span><span class="n">Name</span><span class="p">)</span><span class="s2">&quot;</span> +<span class="p">}</span> +</code></pre></div> + +<p>Have you ever been in the need to remove files based on other file content? Bello a script where I read a file that has the names of files that I want to remove. </p> +<div class="highlight"><pre><span></span><code><span class="k">foreach</span><span class="p">(</span><span class="nv">$line</span> <span class="k">in</span> <span class="nb">Get-Content</span> <span class="p">.\</span><span class="n">Desktop</span><span class="p">\</span><span class="n">bad_files</span><span class="p">.</span><span class="n">txt</span><span class="p">)</span> <span class="p">{</span> + <span class="k">if</span> <span class="p">(</span><span class="nb">Test-Path</span><span class="p">(</span><span class="s1">&#39;\\x.y.z.a\c$\TOTVS\protheus_data\xmls\&#39;</span><span class="p">+</span><span class="nv">$line</span><span class="p">+</span><span class="s1">&#39;.xml&#39;</span><span class="p">))</span> <span class="p">{</span> + <span class="nb">Remove-Item</span><span class="p">(</span><span class="s1">&#39;\\x.y.z.a\c$\TOTVS\protheus_data\xmls\&#39;</span><span class="p">+</span><span class="nv">$line</span><span class="p">+</span><span class="s1">&#39;.xml&#39;</span><span class="p">)</span> + <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> + <span class="nb">echo </span><span class="nv">$line</span> <span class="p">+</span> <span class="s1">&#39; - File not found&#39;</span> + <span class="p">}</span> +<span class="p">}</span> +</code></pre></div> + +<p>And a bonus script to stop/start services (if you handle some Protheus Server, you know why I do that).</p> +<div class="highlight"><pre><span></span><code><span class="nv">$servicesNames</span> <span class="p">=</span> <span class="s1">&#39;app_main&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker1&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker2&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker3&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker4&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker5&#39;</span> + +<span class="nb">Write-host</span> <span class="s2">&quot;Stoping Services&quot;</span> +<span class="nb">Write-host</span> <span class="s2">&quot;--------------------------&quot;</span> + +<span class="k">foreach</span> <span class="p">(</span><span class="nv">$srv</span> <span class="k">in</span> <span class="nv">$servicesNames</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Write-host</span> <span class="s2">&quot;Stopping: &quot;</span> <span class="p">+</span> <span class="nv">$srv</span> + <span class="nv">$SrvPID</span> <span class="p">=</span> <span class="p">(</span><span class="nb">get-wmiobject</span> <span class="n">win32_service</span> <span class="p">|</span> <span class="nb">where </span><span class="p">{</span> <span class="nv">$_</span><span class="p">.</span><span class="n">name</span> <span class="o">-eq</span> <span class="nv">$srv</span><span class="p">}).</span><span class="n">processID</span> + <span class="nb">Write-host</span> <span class="s2">&quot;PID: &quot;</span> <span class="p">+</span> <span class="nv">$SrvPID</span> + + <span class="cm">&lt;# Force if the proccess is stucked #&gt;</span> + <span class="nb">Stop-Process</span> <span class="nv">$SrvPID</span> <span class="n">-Force</span> + <span class="nb">Write-host</span> <span class="s2">&quot;PDI &quot;</span> <span class="p">+</span> <span class="nv">$SrvPID</span> <span class="p">+</span> <span class="s2">&quot; stopped&quot;</span> +<span class="p">}</span> + + +<span class="nb">Write-host</span> <span class="s2">&quot;Starting Services&quot;</span> +<span class="nb">Write-host</span> <span class="s2">&quot;--------------------------&quot;</span> + +<span class="k">foreach</span> <span class="p">(</span><span class="nv">$srv</span> <span class="k">in</span> <span class="nv">$servicesNames</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Write-host</span> <span class="s2">&quot;Starting: &quot;</span> <span class="p">+</span> <span class="nv">$srv</span> + <span class="nb">Start-Service</span> <span class="nv">$srv</span> +<span class="p">}</span> +</code></pre></div> + +<p>Do you have any automated script? Share with us :)</p>Top Level Statement in C# 92020-07-29T19:00:00-03:002020-07-29T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-07-29:/top_level_statement_csharp_9.html<p>Hey folks, I'm coming along to tell you a few things about the new feature of C# 9. Every time you want to start a new project, you always have the same Main File, with the same structure. At the next version of C# (version 9), we'll have a new …</p><p>Hey folks, I'm coming along to tell you a few things about the new feature of C# 9. Every time you want to start a new project, you always have the same Main File, with the same structure. At the next version of C# (version 9), we'll have a new feature called <code>Top Level Statement</code>. With that, we'll be able to code our app without any namespace/class/public void static main structure. Take a look at the code below.</p> +<div class="highlight"><pre><span></span><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span> + +<span class="n">Console</span><span class="p">.</span><span class="n">WriteLine</span><span class="p">(</span><span class="s">&quot;Hello World!&quot;</span><span class="p">);</span> +</code></pre></div> + +<p>It looks pretty simple, but with this, you can play around with your code, and even code a simple/tiny Web API. To start playing with the new features, firstly download the <a href="https://dotnet.microsoft.com/download/dotnet/5.0">.net 5 SDK</a> and change your <code>.csproj</code> file to target the .net 5 and language preview like bellow.</p> +<div class="highlight"><pre><span></span><code><span class="nt">&lt;Project</span> <span class="na">Sdk=</span><span class="s">&quot;Microsoft.NET.Sdk&quot;</span><span class="nt">&gt;</span> + <span class="nt">&lt;PropertyGroup&gt;</span> + <span class="nt">&lt;OutputType&gt;</span>Exe<span class="nt">&lt;/OutputType&gt;</span> + <span class="nt">&lt;TargetFramework&gt;</span>net5.0<span class="nt">&lt;/TargetFramework&gt;</span> + <span class="nt">&lt;LangVersion&gt;</span>preview<span class="nt">&lt;/LangVersion&gt;</span> + <span class="nt">&lt;/PropertyGroup&gt;</span> +<span class="nt">&lt;/Project&gt;</span> +</code></pre></div> + +<p>And you're ready to play with the awesome features available in the preview. Let's code a way to get the image of the day from NASA API and print the Picture of the Day. No awesome code here, it's really a way to show how simple a simple call could be. After here, why not save the image in a file? Maybe send the file over telegram?</p> +<div class="highlight"><pre><span></span><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Net.Http</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Text.Json</span><span class="p">;</span> + +<span class="kt">var</span> <span class="n">API</span> <span class="p">=</span> <span class="s">&quot;https://api.nasa.gov/planetary/apod?hd=true&amp;api_key=DEMO_KEY&quot;</span><span class="p">;</span> +<span class="kt">var</span> <span class="n">cli</span> <span class="p">=</span> <span class="k">new</span> <span class="n">HttpClient</span><span class="p">();</span> + +<span class="kt">var</span> <span class="n">response</span> <span class="p">=</span> <span class="k">await</span> <span class="n">cli</span><span class="p">.</span><span class="n">GetAsync</span><span class="p">(</span><span class="n">API</span><span class="p">);</span> +<span class="kt">var</span> <span class="n">data</span> <span class="p">=</span> <span class="n">JsonSerializer</span><span class="p">.</span><span class="n">Deserialize</span><span class="p">&lt;</span><span class="n">NasaApi</span><span class="p">&gt;(</span><span class="k">await</span> <span class="n">response</span><span class="p">.</span><span class="n">Content</span><span class="p">.</span><span class="n">ReadAsStringAsync</span><span class="p">());</span> + +<span class="n">Console</span><span class="p">.</span><span class="n">WriteLine</span><span class="p">(</span><span class="n">data</span><span class="p">.</span><span class="n">Url</span><span class="p">);</span> +</code></pre></div> + +<p>That's it for today folks. Keep an eye open for the awesome features C# 9 will bring to us, there's plenty more features already available.</p>Zabbix poller processes more than 75%2020-07-02T19:00:00-03:002020-07-02T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-07-02:/zabbix-poller-processes-more-than-75.html<p>Hey folks, this is the third post about tweaking the Zabbix configurations. All changes that I've suggested here were based on a Zabbix Server with 50+ hosts. Another thing that can happen to your server, it's the poller get overwhelmed by the amount of servers that need to be polled …</p><p>Hey folks, this is the third post about tweaking the Zabbix configurations. All changes that I've suggested here were based on a Zabbix Server with 50+ hosts. Another thing that can happen to your server, it's the poller get overwhelmed by the amount of servers that need to be polled plus the ones that are not responding. Bellow two images where you can see the log and the graphic where you can see the usage percent. </p> +<p><img alt="Dashboard log about the poller processes" src="/images/zabbix_pooler.png"></p> +<p><img alt="Graph showing the utilization percent of each collector" src="/images/zabbix_pooler_3.png"></p> +<p>To solve, let's go back to the <code>zabbix_server.conf</code> file and find two variables, <code>StartPollers</code> and <code>StartPollersUnreachable</code>. Increase them as needed. There's no magic number, you must see what works for you. But keep in mind that the <code>StartPollersUnreachable</code> is responsible for that host that can't be "reached" (of course) and will hold your poller more time.</p> +<div class="highlight"><pre><span></span><code><span class="c1">### Option: StartPollers</span> +<span class="c1"># Number of pre-forked instances of pollers.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 0-1000</span> +<span class="c1"># Default:</span> +<span class="na">StartPollers</span><span class="o">=</span><span class="s">20</span> + +<span class="c1">#...</span> + +<span class="c1">### Option: StartPollersUnreachable</span> +<span class="c1"># Number of pre-forked instances of pollers for unreachable hosts (including IPMI and Java).</span> +<span class="c1"># At least one poller for unreachable hosts must be running if regular, IPMI or Java pollers</span> +<span class="c1"># are started.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 0-1000</span> +<span class="c1"># Default:</span> +<span class="na">StartPollersUnreachable</span><span class="o">=</span><span class="s">5</span> +</code></pre></div> + +<p>After the change, restart the server and wait a few moments and take a look again at your dashboard. Bellow the effect that I've got.</p> +<p><img alt="Graph showing the new utilization percent of the processes after the changes" src="/images/zabbix_pooler_4.png"></p>Monitoring a Website heath with Azure Functions2020-06-22T19:00:00-03:002020-06-22T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-06-22:/monitoring-website-heath-with-azure-functions.html<p>Sometimes you get your self in need to monitor a website's health or it's content for changes. Of course, there's plenty of options out there, but for the sake of curiosity, let's code our own to see what we can do. First things first. Everything you'll see here, you can …</p><p>Sometimes you get your self in need to monitor a website's health or it's content for changes. Of course, there's plenty of options out there, but for the sake of curiosity, let's code our own to see what we can do. First things first. Everything you'll see here, you can achieve with the <a href="https://azure.microsoft.com/free/">free tier</a> of azure.</p> +<p>The main idea of our app will be to monitor website health (status code). To create a new Azure Function Project, follow the steps below.</p> +<p><img alt="Steps to create a azure function project" src="/images/azure_functions.gif"></p> +<p>After creating the project, you'll have a few files. Open your main file and start coding. The main file will have a function called <code>Run</code> and you can code your request method. I've created an <code>async</code> method to make the request and log the output at the console. The full code you can see below.</p> +<div class="highlight"><pre><span></span><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Linq</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Net.Http</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Threading.Tasks</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">Microsoft.Azure.WebJobs</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">Microsoft.Azure.WebJobs.Host</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">Microsoft.Extensions.Logging</span><span class="p">;</span> + +<span class="k">namespace</span> <span class="nn">Sipmann.CheckMySite</span> +<span class="p">{</span> + <span class="k">public</span> <span class="k">static</span> <span class="k">class</span> <span class="nc">HttpCheck</span> + <span class="p">{</span> + + <span class="k">private</span> <span class="k">static</span> <span class="k">async</span> <span class="n">Task</span> <span class="nf">GetTask</span><span class="p">(</span><span class="kt">string</span> <span class="n">url</span><span class="p">,</span> <span class="n">ILogger</span> <span class="n">log</span><span class="p">)</span> + <span class="p">{</span> + <span class="kt">var</span> <span class="n">request</span> <span class="p">=</span> <span class="k">new</span> <span class="n">HttpRequestMessage</span><span class="p">(</span><span class="n">HttpMethod</span><span class="p">.</span><span class="n">Get</span><span class="p">,</span> <span class="n">url</span><span class="p">);</span> + + <span class="kt">var</span> <span class="n">client</span> <span class="p">=</span> <span class="k">new</span> <span class="n">HttpClient</span><span class="p">();</span> + <span class="kt">var</span> <span class="n">response</span> <span class="p">=</span> <span class="k">await</span> <span class="n">client</span><span class="p">.</span><span class="n">SendAsync</span><span class="p">(</span><span class="n">request</span><span class="p">);</span> + + <span class="k">if</span> <span class="p">(</span><span class="n">response</span><span class="p">.</span><span class="n">IsSuccessStatusCode</span><span class="p">)</span> + <span class="p">{</span> + <span class="n">log</span><span class="p">.</span><span class="n">LogInformation</span><span class="p">(</span><span class="err">$</span><span class="s">&quot;URL ${url} esta OK&quot;</span><span class="p">);</span> + <span class="p">}</span> + <span class="k">else</span> + <span class="p">{</span> + <span class="n">log</span><span class="p">.</span><span class="n">LogInformation</span><span class="p">(</span><span class="err">$</span><span class="s">&quot;URL ${url} não esta OK&quot;</span><span class="p">);</span> + <span class="p">}</span> + <span class="p">}</span> + +<span class="na"> [FunctionName(&quot;HttpCheck&quot;)]</span> + <span class="k">public</span> <span class="k">static</span> <span class="k">void</span> <span class="nf">Run</span><span class="p">([</span><span class="n">TimerTrigger</span><span class="p">(</span><span class="s">&quot;0 */5 * * * *&quot;</span><span class="p">)]</span><span class="n">TimerInfo</span> <span class="n">myTimer</span><span class="p">,</span> <span class="n">ILogger</span> <span class="n">log</span><span class="p">)</span> + <span class="p">{</span> + <span class="kt">var</span> <span class="n">urls</span> <span class="p">=</span> <span class="k">new</span><span class="p">[]{</span><span class="s">&quot;https://www.sipmann.com&quot;</span><span class="p">,</span> <span class="s">&quot;https://www.canezecanez.com.br&quot;</span><span class="p">};</span> + + <span class="c1">// Start every request and wait for them all to complete</span> + <span class="n">Task</span><span class="p">.</span><span class="n">WaitAll</span><span class="p">(</span><span class="n">urls</span><span class="p">.</span><span class="n">Select</span><span class="p">(</span><span class="n">url</span> <span class="p">=&gt;</span> <span class="n">GetTask</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">log</span><span class="p">)).</span><span class="n">ToArray</span><span class="p">());</span> + <span class="n">log</span><span class="p">.</span><span class="n">LogInformation</span><span class="p">(</span><span class="err">$</span><span class="s">&quot;Finalizou a fila&quot;</span><span class="p">);</span> + <span class="p">}</span> + <span class="p">}</span> +<span class="p">}</span> +</code></pre></div> + +<p>Now you can enhance the function and maybe send some alerts like a Telegram message when one of your sites went down.</p>Azure Data Fundamentals certification with 80% discount2020-06-09T12:30:00-03:002020-06-09T12:30:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-06-09:/azure-data-fundamentals-certification-80-discount.html<p>Hey folks, if you want to achieve some certification this year, keep an eye open for vouchers. A few months ago, Oracle released a set of free courses with certifications. Now it's Microsoft time. Microsoft is updating they're certifications and we have a voucher of 80% discount using the coupon …</p><p>Hey folks, if you want to achieve some certification this year, keep an eye open for vouchers. A few months ago, Oracle released a set of free courses with certifications. Now it's Microsoft time. Microsoft is updating they're certifications and we have a voucher of 80% discount using the coupon <strong>DP900Norfolk</strong> at the checkout of the beta certification DP-900. </p> +<p>Be aware that this certification is in beta and the result won't be instantly available as the regular ones. Access the following link and schedule your exam. <a href="https://docs.microsoft.com/pt-br/learn/certifications/exams/dp-900" target="_blank">https://docs.microsoft.com/pt-br/learn/certifications/exams/dp-900</a>.</p> +<p><strong>Update:</strong> There is a 80% voucher also for <a href="https://docs.microsoft.com/en-us/learn/certifications/azure-ai-fundamentals" target="_blank">https://docs.microsoft.com/en-us/learn/certifications/azure-ai-fundamentals</a>. Voucher: <strong>AI900Saratoga</strong></p>Zabbix ICMP pinger processes more than 75%2020-05-25T16:00:00-03:002020-05-25T16:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-05-25:/zabbix-icmp-pinger-processes-more-than-75.html<p>So your monitoring sytems have grown and your zabbix started loggin "Zabbix icmp pinger processes more than 75% busy" at the dashboard.</p> +<p><img alt="Dashboard do zabbix avisando sobre o erro" src="/images/zabbix_pinger01.png"></p> +<p>All you have to do is open your config file (<code>/etc/zabbix/zabbix_server.conf</code>) and find the a tag named <code>StartPingers</code>. It'll be commented by default. Uncomment it …</p><p>So your monitoring sytems have grown and your zabbix started loggin "Zabbix icmp pinger processes more than 75% busy" at the dashboard.</p> +<p><img alt="Dashboard do zabbix avisando sobre o erro" src="/images/zabbix_pinger01.png"></p> +<p>All you have to do is open your config file (<code>/etc/zabbix/zabbix_server.conf</code>) and find the a tag named <code>StartPingers</code>. It'll be commented by default. Uncomment it and set it's value to something like 3 or 4. It should solve your problem.</p> +<div class="highlight"><pre><span></span><code><span class="c1">### Option: StartPingers</span> +<span class="c1"># Number of pre-forked instances of ICMP pingers.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 0-1000</span> +<span class="c1"># Default:</span> +<span class="nv">StartPingers</span><span class="o">=</span><span class="m">4</span> +</code></pre></div> + +<h2>How many Pingers do I need?</h2> +<p>Well, there is no exact answer to this. If you set it too high, you'll be wasting resources. The best way to solve, it's increasing them as soon as you notice the percentage growing.</p>Zabbix Server Out of Memory2020-02-27T19:00:00-03:002020-02-27T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-02-27:/zabbix-server-out-of-memory-crash.html<p>Do you have a crashing Zabbix Server and looking through the log <code>/var/log/zabbix/zabbix_server.log</code> you see the following out of memory message?</p> +<div class="highlight"><pre><span></span><code>__mem_malloc: skipped <span class="m">0</span> asked <span class="m">24</span> skip_min <span class="m">18446744073709551615</span> skip_max <span class="m">0</span> +<span class="o">[</span>file:dbconfig.c,line:94<span class="o">]</span> __zbx_mem_realloc<span class="o">()</span>: out of memory <span class="o">(</span>requested <span class="m">16</span> bytes<span class="o">)</span> +<span class="o">[</span>file:dbconfig.c,line …</code></pre></div><p>Do you have a crashing Zabbix Server and looking through the log <code>/var/log/zabbix/zabbix_server.log</code> you see the following out of memory message?</p> +<div class="highlight"><pre><span></span><code>__mem_malloc: skipped <span class="m">0</span> asked <span class="m">24</span> skip_min <span class="m">18446744073709551615</span> skip_max <span class="m">0</span> +<span class="o">[</span>file:dbconfig.c,line:94<span class="o">]</span> __zbx_mem_realloc<span class="o">()</span>: out of memory <span class="o">(</span>requested <span class="m">16</span> bytes<span class="o">)</span> +<span class="o">[</span>file:dbconfig.c,line:94<span class="o">]</span> __zbx_mem_realloc<span class="o">()</span>: please increase CacheSize configuration parameter +</code></pre></div> + +<p>Besides the clear solution to the error, that's a common issue on servers that have a few monitoring items on it (servers, switches, firewalls, databases, etc...). To solve, go to your zabbix_server.conf and look for the CacheSize property and set it to a higher value. Its default should be 8M. At a customer that has somewhere between 4 servers, 7 firewalls/appliances, and a few other things, a 32M did the job, but you can set up to 8G.</p> +<p>See ya folks.</p>Flutter + firebase auth crashing2019-10-03T19:00:00-03:002019-10-03T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2019-10-03:/flutter_with_firebase_auth_crashing.html<p>Hey Folks, recently I've started learning <a href="https://flutter.dev/">Flutter</a> and right after a TODO List, I tried a Firebase integration. But as soon as I started setting the dependencies, my app stopped opening... just a crash. After a few logs digging, I've found the following log.</p> +<div class="highlight"><pre><span></span><code>AndroidRuntime: FATAL EXCEPTION: main +AndroidRuntime: Process …</code></pre></div><p>Hey Folks, recently I've started learning <a href="https://flutter.dev/">Flutter</a> and right after a TODO List, I tried a Firebase integration. But as soon as I started setting the dependencies, my app stopped opening... just a crash. After a few logs digging, I've found the following log.</p> +<div class="highlight"><pre><span></span><code>AndroidRuntime: FATAL EXCEPTION: main +AndroidRuntime: Process: com.example.diadocasal, PID: <span class="m">13672</span> +AndroidRuntime: java.lang.NoClassDefFoundError: Failed resolution of: Landroid/support/v4/util/ArrayMap<span class="p">;</span> +AndroidRuntime: at com.google.android.gms.internal.measurement.zzca.&lt;clinit&gt;<span class="o">(</span>Unknown Source:60<span class="o">)</span> +AndroidRuntime: at com.google.android.gms.internal.measurement.zzcm.zzr<span class="o">(</span>Unknown Source:7<span class="o">)</span> +AndroidRuntime: at com.google.android.gms.measurement.internal.zzfj.&lt;init&gt;<span class="o">(</span>Unknown Source:23<span class="o">)</span> +</code></pre></div> + +<p>Notice the "NoClassDefFound" of an ArrayMap. To solve that I did the following changes to the files:</p> +<div class="highlight"><pre><span></span><code><span class="c1">//build.gradle file</span> + <span class="n">ext</span><span class="p">.</span><span class="na">kotlin_version</span> <span class="o">=</span> <span class="err">&#39;</span><span class="mf">1.3.20</span><span class="err">&#39;</span> +<span class="o">[</span><span class="p">...</span><span class="o">]</span> + <span class="n">dependencies</span> <span class="p">{</span> + <span class="n">classpath</span> <span class="err">&#39;</span><span class="n">com</span><span class="p">.</span><span class="na">android</span><span class="p">.</span><span class="na">tools</span><span class="p">.</span><span class="na">build</span><span class="p">:</span><span class="n">gradle</span><span class="p">:</span><span class="mf">3.3.0</span><span class="err">&#39;</span> <span class="c1">// gradle version</span> +</code></pre></div> + +<div class="highlight"><pre><span></span><code><span class="c1">;gradle.properties file</span> +<span class="na">org.gradle.jvmargs</span><span class="o">=</span><span class="s">-Xmx1536M ;mine have just this line at first</span> +<span class="na">android.useAndroidX</span><span class="o">=</span><span class="s">true ; uses androidX instead of the default support library</span> +<span class="na">android.enableJetifier</span><span class="o">=</span><span class="s">true ; uses jetpack libraries</span> +<span class="na">android.enableR8</span><span class="o">=</span><span class="s">true ; the new code shriker</span> +</code></pre></div> + +<p>After that, voilà, app up and running.</p>Removing a user from SQL Server database who owns a schema2019-09-06T07:00:00-03:002020-10-21T18:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2019-09-06:/removing-user-from-sql-server-database.html<p>Your customer urge you to drop a user from the MsSQL Server database, but you stuck with the following related error:</p> +<div class="highlight"><pre><span></span><code><span class="n">Error</span><span class="o">:</span> <span class="mi">15138</span> <span class="n">The</span> <span class="n">database</span> <span class="n">principal</span> <span class="n">owns</span> <span class="n">a</span> <span class="n">schema</span> <span class="k">in</span> <span class="n">the</span> <span class="n">database</span><span class="o">,</span> <span class="n">and</span> <span class="n">cannot</span> <span class="n">be</span> <span class="n">dropped</span><span class="o">.</span> +</code></pre></div> + +<p>That means that the user owns one or more shcemas of your database. If …</p><p>Your customer urge you to drop a user from the MsSQL Server database, but you stuck with the following related error:</p> +<div class="highlight"><pre><span></span><code><span class="n">Error</span><span class="o">:</span> <span class="mi">15138</span> <span class="n">The</span> <span class="n">database</span> <span class="n">principal</span> <span class="n">owns</span> <span class="n">a</span> <span class="n">schema</span> <span class="k">in</span> <span class="n">the</span> <span class="n">database</span><span class="o">,</span> <span class="n">and</span> <span class="n">cannot</span> <span class="n">be</span> <span class="n">dropped</span><span class="o">.</span> +</code></pre></div> + +<p>That means that the user owns one or more shcemas of your database. If you don't have access to the SSMS to see which schema or objects the user owns, the following SQL should do the job.</p> +<div class="highlight"><pre><span></span><code><span class="k">USE</span><span class="w"> </span><span class="o">[</span><span class="n">DATABASENAME</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> + +<span class="k">select</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Objeto</span><span class="p">,</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Owner</span><span class="w"></span> +<span class="k">from</span><span class="w"> </span><span class="n">sys</span><span class="p">.</span><span class="n">schemas</span><span class="w"> </span><span class="n">so</span><span class="w"></span> +<span class="k">inner</span><span class="w"> </span><span class="k">join</span><span class="w"> </span><span class="n">sysusers</span><span class="w"> </span><span class="n">su</span><span class="w"> </span><span class="k">on</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">principal_id</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">uid</span><span class="w"></span> +<span class="k">where</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">&#39;username&#39;</span><span class="w"></span> + +<span class="k">select</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Objeto</span><span class="p">,</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Owner</span><span class="p">,</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">xtype</span><span class="w"> </span><span class="n">Tipo</span><span class="w"></span> +<span class="k">from</span><span class="w"> </span><span class="n">sys</span><span class="p">.</span><span class="n">sysobjects</span><span class="w"> </span><span class="n">so</span><span class="w"></span> +<span class="k">inner</span><span class="w"> </span><span class="k">join</span><span class="w"> </span><span class="n">sysusers</span><span class="w"> </span><span class="n">su</span><span class="w"> </span><span class="k">on</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">uid</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">uid</span><span class="w"></span> +<span class="k">where</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">&#39;username&#39;</span><span class="w"></span> +</code></pre></div> + +<p>Once you have the objects/schemas owned by the user, you can change them with the following SQL (schema change sample):</p> +<div class="highlight"><pre><span></span><code><span class="k">USE</span><span class="w"> </span><span class="o">[</span><span class="n">DATABASENAME</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +<span class="k">ALTER</span><span class="w"> </span><span class="k">AUTHORIZATION</span><span class="w"> </span><span class="k">ON</span><span class="w"> </span><span class="k">SCHEMA</span><span class="o">::[</span><span class="n">db_datareader</span><span class="o">]</span><span class="w"> </span><span class="k">TO</span><span class="w"> </span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="w"> </span><span class="c1">-- new owner username</span> +<span class="k">ALTER</span><span class="w"> </span><span class="k">AUTHORIZATION</span><span class="w"> </span><span class="k">ON</span><span class="w"> </span><span class="k">SCHEMA</span><span class="o">::[</span><span class="n">db_datawriter</span><span class="o">]</span><span class="w"> </span><span class="k">TO</span><span class="w"> </span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +</code></pre></div> + +<p>Then you're ready to drop the user <code>DROP USER [username]</code></p> +<h2>How to list all the schemas and it's owners?</h2> +<p>Here's a script to list schemas and it's owners.</p> +<div class="highlight"><pre><span></span><code><span class="k">USE</span><span class="w"> </span><span class="o">[</span><span class="n">DATABASENAME</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +<span class="k">SELECT</span><span class="w"></span> +<span class="w"> </span><span class="nf">schema_name</span><span class="p">(</span><span class="nf">schema_id</span><span class="p">)</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="n">schemaname</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="nf">user_name</span><span class="p">(</span><span class="n">schm</span><span class="p">.</span><span class="n">principal_id</span><span class="p">)</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="n">username</span><span class="p">,</span><span class="w"> </span><span class="o">*</span><span class="w"></span> +<span class="k">FROM</span><span class="w"> </span><span class="n">sys</span><span class="p">.</span><span class="n">schemas</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="n">schm</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +</code></pre></div>Limiting Connection Resources on SQL Server2019-08-12T12:00:00-03:002019-08-12T12:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2019-08-12:/limiting-connection-resources-sql-server.html<p>Have you ever suffered from a slow SQLServer database? Someone love to run that heavy query in the database? Resource Governor to the rescue. You can set a few rules on how users (connections actually) will use the server/database resources based on a few things.</p> +<p>First things first, if …</p><p>Have you ever suffered from a slow SQLServer database? Someone love to run that heavy query in the database? Resource Governor to the rescue. You can set a few rules on how users (connections actually) will use the server/database resources based on a few things.</p> +<p>First things first, if you don't have DAC enabled, enable it now. Dealing with resource governor can lock you out of the database and leave you without action (almost... you can start the server with -c -m -f).</p> +<p>Now to understand how Resource Governor works, we have a few keywords <code>resource pool</code>, <code>workload group</code> e <code>Classifier Function</code>.</p> +<p><img alt="Pool Sample" src="/images/sql-pool.png"></p> +<h2>Resource Pool</h2> +<p>First, we have the Resource Pool, with is the bigger resource group that we have the ability to manage. With it, we can set a few things like: <code>MIN_CPU_PERCENT</code>, <code>MAX_CPU_PERCENT</code>, <code>MIN_MEMORY_PERCENT</code>, <code>MAX_MEMORY_PERCENT</code>, <code>MIN_IOPS_PER_VOLUME</code>, and <code>MAX_IOPS_PER_VOLUME</code>.</p> +<p>Be aware that the <code>MAX_CPU_PERCENT</code> will just "works" when there is another connection with a higher priority, otherwise it will use what is available. Let's create a pool.</p> +<div class="highlight"><pre><span></span><code><span class="k">CREATE</span><span class="w"> </span><span class="n">RESOURCE</span><span class="w"> </span><span class="n">POOL</span><span class="w"> </span><span class="o">[</span><span class="n">SpreadSheet</span><span class="o">]</span><span class="w"></span> +<span class="k">WITH</span><span class="w"> </span><span class="p">(</span><span class="w"></span> +<span class="w"> </span><span class="n">MIN_CPU_PERCENT</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">MAX_CPU_PERCENT</span><span class="o">=</span><span class="mi">20</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">MIN_MEMORY_PERCENT</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">MAX_MEMORY_PERCENT</span><span class="o">=</span><span class="mi">20</span><span class="w"></span> +<span class="p">);</span><span class="w"></span> +</code></pre></div> + +<p>## Workload Group</p> +<p>Then we have a workload group that "works" inside a pool, so you can have another granularity on how you can split your resources. Again, we have a few options: <code>IMPORTANCE</code>, <code>REQUEST_MAX_CPU_TIME_SEC</code>, <code>REQUEST_MAX_MEMORY_GRANT_PERCENT</code>, <code>GROUP_MAX_REQUESTS</code>.</p> +<p>The <code>IMPORTANCE</code> set guesses what... the importance of that workload inside the pool, you can set LOW, MEDIUM, HIGH. GROUP_MAX_REQUESTS sets how many requests can run at the same time inside that workload (0 will set as NO LIMIT)</p> +<div class="highlight"><pre><span></span><code><span class="k">CREATE</span><span class="w"> </span><span class="n">WORKLOAD</span><span class="w"> </span><span class="k">GROUP</span><span class="w"> </span><span class="o">[</span><span class="n">DepartmentA</span><span class="o">]</span><span class="w"> </span> +<span class="k">WITH</span><span class="w"> </span><span class="p">(</span><span class="w"></span> +<span class="w"> </span><span class="n">GROUP_MAX_REQUESTS</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">IMPORTANCE</span><span class="o">=</span><span class="n">LOW</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">REQUEST_MAX_CPU_TIME_SEC</span><span class="o">=</span><span class="mi">10</span><span class="p">,</span><span class="w"> </span><span class="c1">-- Time running/using CPU</span> +<span class="w"> </span><span class="n">REQUEST_MAX_MEMORY_GRANT_PERCENT</span><span class="o">=</span><span class="mi">15</span><span class="w"></span> +<span class="p">)</span><span class="w"> </span><span class="k">USING</span><span class="w"> </span><span class="o">[</span><span class="n">SpreadSheet</span><span class="o">]</span><span class="p">;</span><span class="w"> </span><span class="c1">-- pool name here</span> +</code></pre></div> + +<h2>Classifier Function</h2> +<p>This is where everything begins... This is the entry point where you should set the group name. It's a function that will run for every new connection so be aware that if your function runs lots of queries or some heavy stuff... that time will be added to the connection handshake. If the function returns NULL or a group name that doesn't exist, the 'default' group will be used... Yes, there is a default workload group where everything runs where there's no classifier.</p> +<div class="highlight"><pre><span></span><code><span class="k">CREATE</span><span class="w"> </span><span class="k">FUNCTION</span><span class="w"> </span><span class="n">fnClassWorkloadGovernor</span><span class="p">()</span><span class="w"> </span> +<span class="k">RETURNS</span><span class="w"> </span><span class="n">SYSNAME</span><span class="w"> </span><span class="k">WITH</span><span class="w"> </span><span class="n">SCHEMABINDING</span><span class="w"> </span> +<span class="k">AS</span><span class="w"> </span> +<span class="k">BEGIN</span><span class="w"> </span> +<span class="w"> </span><span class="k">IF</span><span class="w"> </span><span class="nf">APP_NAME</span><span class="p">()</span><span class="w"> </span><span class="ow">LIKE</span><span class="w"> </span><span class="s1">&#39;%Excel%&#39;</span><span class="w"></span> +<span class="w"> </span><span class="k">RETURN</span><span class="w"> </span><span class="s1">&#39;DepartmentA&#39;</span><span class="w"></span> + +<span class="w"> </span><span class="k">IF</span><span class="w"> </span><span class="nf">HOST_NAME</span><span class="p">()</span><span class="w"> </span><span class="ow">LIKE</span><span class="w"> </span><span class="s1">&#39;%THAT_MACHINE_OR_APP_SERVER%&#39;</span><span class="w"></span> +<span class="w"> </span><span class="k">RETURN</span><span class="w"> </span><span class="s1">&#39;LowPriority&#39;</span><span class="w"></span> + +<span class="w"> </span><span class="k">RETURN</span><span class="w"> </span><span class="k">NULL</span><span class="w"></span> +<span class="k">END</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> + +<span class="k">ALTER</span><span class="w"> </span><span class="n">RESOURCE</span><span class="w"> </span><span class="n">GOVERNOR</span><span class="w"> </span><span class="k">WITH</span><span class="w"> </span><span class="p">(</span><span class="n">CLASSIFIER_FUNCTION</span><span class="o">=</span><span class="n">dbo</span><span class="p">.</span><span class="n">fnClassWorkloadGovernor</span><span class="p">);</span><span class="w"></span> +<span class="k">ALTER</span><span class="w"> </span><span class="n">RESOURCE</span><span class="w"> </span><span class="n">GOVERNOR</span><span class="w"> </span><span class="k">RECONFIGURE</span><span class="p">;</span><span class="w"></span> +</code></pre></div> + +<p>There you go... now you have a fully working resource governor, but look out that If you want to delete that classifier function, first you have to remove it from the resource governor (look the SCHEMABINDING at the create up there).</p> +<p>To disable Resource Governor</p> +<div class="highlight"><pre><span></span><code><span class="k">ALTER</span><span class="w"> </span><span class="n">RESOURCE</span><span class="w"> </span><span class="n">GOVERNOR</span><span class="w"> </span><span class="k">WITH</span><span class="w"> </span><span class="p">(</span><span class="n">CLASSIFIER_FUNCTION</span><span class="o">=</span><span class="k">null</span><span class="p">)</span><span class="w"></span> +<span class="k">ALTER</span><span class="w"> </span><span class="n">RESOURCE</span><span class="w"> </span><span class="n">GOVERNOR</span><span class="w"> </span><span class="k">RECONFIGURE</span><span class="w"></span> + +<span class="k">ALTER</span><span class="w"> </span><span class="n">RESOURCE</span><span class="w"> </span><span class="n">GOVERNOR</span><span class="w"> </span><span class="n">DISABLE</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +</code></pre></div>Using git hooks to easy your life2019-07-30T20:00:00-03:002019-07-30T20:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2019-07-30:/using_git_hooks_easy_your_life.html<p>Hey folks, it's been a time since my last post. In the meantime, I moved to another state, changed job, and started learning new kinds of stuff. Today I would like to share one thing that I usually do with my small git projects. Git has many cool features, git …</p><p>Hey folks, it's been a time since my last post. In the meantime, I moved to another state, changed job, and started learning new kinds of stuff. Today I would like to share one thing that I usually do with my small git projects. Git has many cool features, git hooks were one of them. I'll talk about the pre-commit hook today.</p> +<p>Let's say that, for some reason, you don't have a CI tool/server running after every commit and you want to enforce that every developer runs the tests before every commit? Git pre-commit to the rescue. You can code the hooks with shell, ruby, python, and I could be wrong, but even PHP would work. pre-commit is a client-side hook (we have server side too) and he's located inside the <cite>.git/hooks</cite> folder. Let's jump to the code... Create a file called 'pre-commit' inside that folder with the following code.</p> +<div class="highlight"><pre><span></span><span class="ch">#!/bin/bash</span> +npm <span class="nb">test</span> <span class="c1"># assuming you&#39;re using it inside a nodeJS project</span> +</pre></div> +<p>Don't forget to make the script executable!! Now break your test and try to commit. That's easy but can save you from breaking the tests at the main CI/Travis/Codeship/etc and being notified by email :). Why not even validate the lint of your project or check if the coverage doesn't fall? Does your team/company have a patter for commit messages? No problem, there is a hook called <cite>commit-msg</cite> that you can use to validate your message.</p> +Microservices with NodeJS, Express.js and RabbitMQ Part 22018-04-13T13:00:00-03:002018-04-13T13:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-04-13:/microservices_nodejs_express_rabbitmq_part_2.html<p>If you haven't read the <a class="reference external" href="https://www.sipmann.com/microservices_nodejs_express_rabbitmq_part_1-en.html">part 1</a> go ahead and read it... It can be useful :). Or if for some reason you want to start now, you can grab the project where we stopped <a class="reference external" href="https://github.com/sipmann/imagecompacter/releases/tag/v1">here</a> and get along. On this part, we'll implement the RabbitMQ queue and see how we …</p><p>If you haven't read the <a class="reference external" href="https://www.sipmann.com/microservices_nodejs_express_rabbitmq_part_1-en.html">part 1</a> go ahead and read it... It can be useful :). Or if for some reason you want to start now, you can grab the project where we stopped <a class="reference external" href="https://github.com/sipmann/imagecompacter/releases/tag/v1">here</a> and get along. On this part, we'll implement the RabbitMQ queue and see how we can get the best of our app and server with that.</p> +<p>Before we began coding, let's understand why we are going to use RabbitMQ if what we have now works? If you check again, you'll see how long it takes to answer the request with the optimized image. It takes a few seconds, so imagine an online service with thousands of request to optimize images (like <a class="reference external" href="https://tinypng.com/">TinyPNG</a>) how long is it gonna take to answer every request? How much of your server is it gonna take? With only one service running, probably the server will crash.</p> +<p>With a queue, we can schedule the requests so we can use the amount of memory and processor that our server has, without taking more than we can. It's better to take a few seconds to answer the request then throw some error to the user. Want more? With RabbitMQ we can see how the queue is doing and we can add more consumers (workers) to it and get things done quicker and distribute the job.</p> +<p>First of all, we need an up and running Rabbit server, for the sake of simplicity, I'll use a Docker container with it inside.</p> +<div class="highlight"><pre><span></span>docker run -d --name rabbit -p <span class="m">5672</span>:5672 -p <span class="m">8080</span>:15672 rabbitmq:3-management +</pre></div> +<p>You can see that we're running the rabbitmq:3-management image, which provides us a web interface to see how things are going. After that, if you look at our code you'll see that all the job is made at the '/upload' route, and that's what we'll change.</p> +<p>First, we need to understand what we need from RabbitMQ. We need something that, we send an image to a queue and get an optimized image back from that. There is a name for that, is RPC (remote procedure call) and there are two ways of doing this with rabbit. Both the ways you can see on their tutorial page. We'll use the approach that uses a global channel whose id is randomly generated (you'll use the name 'amq.rabbitmq.reply-to' but the rabbit will do the job).</p> +<p>Let's start importing the library, defining a few variables and defining a init function that will establish a connection with the rabbit server and create our RPC queue. The RPC queue it's where we'll receive the answer from the consumer (our worker).</p> +<div class="highlight"><pre><span></span><span class="c1">//import the library</span> +<span class="kr">const</span> <span class="nx">amqplib</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;amqplib&#39;</span><span class="p">);</span> + +<span class="c1">//queue channel</span> +<span class="kd">let</span> <span class="nx">channel</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span> +<span class="c1">//queue name</span> +<span class="kr">const</span> <span class="nx">QUEUE</span> <span class="o">=</span> <span class="s1">&#39;optimizeimg&#39;</span><span class="p">;</span> + +<span class="c1">//...</span> + +<span class="kd">function</span> <span class="nx">init</span><span class="p">()</span> <span class="p">{</span> + <span class="k">return</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;amqplib&#39;</span><span class="p">).</span><span class="nx">connect</span><span class="p">(</span><span class="s1">&#39;amqp://localhost&#39;</span><span class="p">)</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">conn</span> <span class="p">=&gt;</span> <span class="nx">conn</span><span class="p">.</span><span class="nx">createChannel</span><span class="p">())</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">ch</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="nx">channel</span> <span class="o">=</span> <span class="nx">ch</span><span class="p">;</span> + + <span class="c1">//this queue is a &quot;Direct reply-to&quot; read more at the docs</span> + <span class="c1">//When some msg comes in, we &quot;emit&quot; a message to the proper &quot;correlationId&quot; listener</span> + <span class="nx">ch</span><span class="p">.</span><span class="nx">consume</span><span class="p">(</span><span class="s1">&#39;amq.rabbitmq.reply-to&#39;</span><span class="p">,</span> <span class="nx">msg</span> <span class="p">=&gt;</span> <span class="nx">eventEmitter</span><span class="p">.</span><span class="nx">emit</span><span class="p">(</span><span class="nx">msg</span><span class="p">.</span><span class="nx">properties</span><span class="p">.</span><span class="nx">correlationId</span><span class="p">,</span> <span class="nx">msg</span><span class="p">.</span><span class="nx">content</span><span class="p">),</span> <span class="p">{</span><span class="nx">noAck</span><span class="o">:</span> <span class="kc">true</span><span class="p">});</span> + <span class="p">});</span> +<span class="p">}</span> + +<span class="c1">//Random id generator</span> +<span class="kd">function</span> <span class="nx">randomid</span><span class="p">()</span> <span class="p">{</span> + <span class="k">return</span> <span class="k">new</span> <span class="nb">Date</span><span class="p">().</span><span class="nx">getTime</span><span class="p">().</span><span class="nx">toString</span><span class="p">()</span> <span class="o">+</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">random</span><span class="p">().</span><span class="nx">toString</span><span class="p">()</span> <span class="o">+</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">random</span><span class="p">().</span><span class="nx">toString</span><span class="p">();</span> +<span class="p">}</span> + +<span class="nx">app</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="s1">&#39;/upload&#39;</span><span class="p">,</span> <span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="kd">let</span> <span class="nx">img</span> <span class="o">=</span> <span class="nx">req</span><span class="p">.</span><span class="nx">files</span><span class="p">.</span><span class="nx">image</span><span class="p">;</span> + + <span class="kd">let</span> <span class="nx">id</span> <span class="o">=</span> <span class="nx">randomid</span><span class="p">();</span> + + <span class="c1">//Event listener that will fire when the proper randomid is provided</span> + <span class="nx">eventEmitter</span><span class="p">.</span><span class="nx">once</span><span class="p">(</span><span class="nx">id</span><span class="p">,</span> <span class="nx">msg</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="nx">res</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="nx">msg</span><span class="p">,</span> <span class="s1">&#39;binary&#39;</span><span class="p">);</span> + <span class="nx">res</span><span class="p">.</span><span class="nx">end</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="s1">&#39;binary&#39;</span><span class="p">);</span> + <span class="p">});</span> + + <span class="c1">//Checks if the queue exists, and create it if needed.</span> + <span class="nx">channel</span><span class="p">.</span><span class="nx">assertQueue</span><span class="p">(</span><span class="nx">QUEUE</span><span class="p">)</span> + <span class="c1">//Sent the buffered img to the queue with the ID and the responseQueue</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="nx">channel</span><span class="p">.</span><span class="nx">sendToQueue</span><span class="p">(</span><span class="nx">QUEUE</span><span class="p">,</span> <span class="nx">img</span><span class="p">.</span><span class="nx">data</span><span class="p">,</span> <span class="p">{</span><span class="nx">correlationId</span><span class="o">:</span><span class="nx">id</span><span class="p">,</span> <span class="nx">replyTo</span><span class="o">:</span> <span class="s1">&#39;amq.rabbitmq.reply-to&#39;</span><span class="p">}));</span> + +<span class="p">});</span> + +<span class="c1">//Finally start the app with the given port number</span> +<span class="c1">//now we initialize the rabbitmq connection before start the server</span> +<span class="nx">init</span><span class="p">()</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="nx">app</span><span class="p">.</span><span class="nx">listen</span><span class="p">(</span><span class="mi">4000</span><span class="p">,</span> <span class="p">()</span> <span class="p">=&gt;</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;Example app listening on port 4000!&#39;</span><span class="p">)))</span> + <span class="p">.</span><span class="k">catch</span><span class="p">(</span><span class="nx">err</span><span class="p">=&gt;</span><span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="nx">err</span><span class="p">));</span> +</pre></div> +<p>Ok, now we have our server code rewritten so let's see our worker code. Create a file named 'worker.js' and let's see how it's gonna be. It's really simple. You initialize a connection with RabbitMQ too, create a channel, check if the queue exists and start watching for incoming messages. When an image arrives, we do the job with it and send back to the &quot;replyTo&quot; queue the optimized image for the proper sender (correlationId). In the end, we do an acknowledge of the message so it get's out from the queue.</p> +<div class="highlight"><pre><span></span><span class="kr">const</span> <span class="nx">imagemin</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;imagemin&#39;</span><span class="p">);</span> +<span class="kr">const</span> <span class="nx">imageminPngquant</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;imagemin-pngquant&#39;</span><span class="p">);</span> + +<span class="kd">let</span> <span class="nx">channel</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span> +<span class="kr">const</span> <span class="nx">QUEUE</span> <span class="o">=</span> <span class="s1">&#39;imgqueue&#39;</span><span class="p">;</span> + +<span class="nx">require</span><span class="p">(</span><span class="s1">&#39;amqplib&#39;</span><span class="p">).</span><span class="nx">connect</span><span class="p">(</span><span class="s1">&#39;amqp://localhost&#39;</span><span class="p">)</span> +<span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">conn</span> <span class="p">=&gt;</span><span class="nx">conn</span><span class="p">.</span><span class="nx">createChannel</span><span class="p">())</span> +<span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">ch</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="nx">ch</span><span class="p">.</span><span class="nx">assertQueue</span><span class="p">(</span><span class="nx">QUEUE</span><span class="p">)</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="c1">//Watch incomming messages</span> + <span class="nx">ch</span><span class="p">.</span><span class="nx">consume</span><span class="p">(</span><span class="nx">QUEUE</span><span class="p">,</span> <span class="nx">msg</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="nx">imagemin</span><span class="p">.</span><span class="nx">buffer</span><span class="p">(</span><span class="nx">msg</span><span class="p">.</span><span class="nx">content</span><span class="p">,</span> <span class="p">{</span> + <span class="nx">plugins</span><span class="o">:</span> <span class="p">[</span><span class="nx">imageminPngquant</span><span class="p">()]</span> + <span class="p">})</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">out</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="c1">//Send back to the sender (replyTo) queue and give the correlationId back</span> + <span class="c1">//so we can emit the event.</span> + <span class="nx">ch</span><span class="p">.</span><span class="nx">sendToQueue</span><span class="p">(</span><span class="nx">msg</span><span class="p">.</span><span class="nx">properties</span><span class="p">.</span><span class="nx">replyTo</span><span class="p">,</span> <span class="nx">out</span><span class="p">,</span> <span class="p">{</span> + <span class="nx">correlationId</span><span class="o">:</span> <span class="nx">msg</span><span class="p">.</span><span class="nx">properties</span><span class="p">.</span><span class="nx">correlationId</span> + <span class="p">});</span> + + <span class="c1">//Acknowledge the job done with the message.</span> + <span class="nx">ch</span><span class="p">.</span><span class="nx">ack</span><span class="p">(</span><span class="nx">msg</span><span class="p">);</span> + <span class="p">});</span> + <span class="p">});</span> + <span class="p">});</span> +<span class="p">});</span> +</pre></div> +<p>The key points here are. Open just one connection to the hole server. You CAN create one channel for every request that you receive, but it can take some time if you have a really big cluster of RabbitMQ. It was a quick tutorial, but I hope that it was able to clear a few questions that you might have when working with rabbit and express.</p> +Microservices with NodeJS, Express.js and RabbitMQ Part 12018-04-04T11:25:00-03:002018-04-04T11:25:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-04-04:/microservices_nodejs_express_rabbitmq_part_1.html<p>This is the first part of a microservices development series. The service will consist of the bellow architecture, where we will expose an image optimizer service that will forward the request to a <a class="reference external" href="https://www.rabbitmq.com/">RabbitMQ</a> queue and answer with the bytecode of the optimized image. It shouldn't be a long series …</p><p>This is the first part of a microservices development series. The service will consist of the bellow architecture, where we will expose an image optimizer service that will forward the request to a <a class="reference external" href="https://www.rabbitmq.com/">RabbitMQ</a> queue and answer with the bytecode of the optimized image. It shouldn't be a long series so let's see what we can do.</p> +<img alt="Service architecture" src="/images/microservices_rabit_pt1.png" /> +<p>Let's get our environment working. First, we'll need to install the libraries that we'll use.</p> +<p>Create a dir and initialize the nodejs application inside it (<cite>npm init</cite>) and then let's install the deps.</p> +<ul class="simple"> +<li>amqplib - AMQP lib to interact with rabbitmq</li> +<li>express - Do our basic rest API</li> +<li>express-fileupload - easy file upload parser</li> +<li>imagemin and imagemin-pngquant - our image compacter</li> +</ul> +<div class="highlight"><pre><span></span>npm install --save express amqplib express-fileupload imagemin imagemin-pngquant +</pre></div> +<p>Now let's write the entry points for our service, we'll have two basic entry points. The path <cite>/</cite> that will have a welcome message, the second path will be <cite>/upload</cite> and this is the one that will handle the image and produce a job for our workers.</p> +<div class="highlight"><pre><span></span><span class="kr">const</span> <span class="nx">express</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;express&#39;</span><span class="p">);</span> +<span class="kr">const</span> <span class="nx">fileUpload</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;express-fileupload&#39;</span><span class="p">);</span> + +<span class="c1">//Instantiate the app and set the fileupload parser to manage files</span> +<span class="kr">const</span> <span class="nx">app</span> <span class="o">=</span> <span class="nx">express</span><span class="p">();</span> +<span class="nx">app</span><span class="p">.</span><span class="nx">use</span><span class="p">(</span><span class="nx">fileUpload</span><span class="p">());</span> + +<span class="c1">//Our index entry point</span> +<span class="nx">app</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;/&#39;</span><span class="p">,</span> <span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="nx">res</span><span class="p">.</span><span class="nx">send</span><span class="p">(</span><span class="s1">&#39;Hello From ImageCompacter service&#39;</span><span class="p">));</span> + +<span class="c1">//The path that will handle the image file and throw them to the queue</span> +<span class="nx">app</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="s1">&#39;/upload&#39;</span><span class="p">,</span> <span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="c1">//With express-fileupload we can grab the files like this</span> + <span class="kd">let</span> <span class="nx">img</span> <span class="o">=</span> <span class="nx">req</span><span class="p">.</span><span class="nx">files</span><span class="p">.</span><span class="nx">image</span><span class="p">;</span> <span class="c1">//&quot;image&quot; is the name of the input</span> + + <span class="nx">res</span><span class="p">.</span><span class="nx">send</span><span class="p">(</span><span class="s1">&#39;Not ready yet&#39;</span><span class="p">);</span> +<span class="p">});</span> + +<span class="c1">//Finally start the app with the given port number</span> +<span class="nx">app</span><span class="p">.</span><span class="nx">listen</span><span class="p">(</span><span class="mi">4000</span><span class="p">,</span> <span class="p">()</span> <span class="p">=&gt;</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;Example app listening on port 4000!&#39;</span><span class="p">));</span> +</pre></div> +<p>Let's check if it works, run the service with node.</p> +<div class="highlight"><pre><span></span>node index.js +Example app listening on port <span class="m">4000</span>! +</pre></div> +<p>Open the browser and check if it prints our hello message when accessing <cite>localhost:4000</cite>. Works? Greate. Now let's work with the image and see how we do it. To optimize our image, we'll use the library imagemin and <a class="reference external" href="https://www.npmjs.com/package/imagemin-pngquant">imagemin-pngquant</a>, it will be that simple for now, we'll work with rabbitmq latter.</p> +<div class="highlight"><pre><span></span><span class="kr">const</span> <span class="nx">imagemin</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;imagemin&#39;</span><span class="p">);</span> +<span class="kr">const</span> <span class="nx">imageminPngquant</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;imagemin-pngquant&#39;</span><span class="p">);</span> +<span class="c1">//...</span> + +<span class="c1">//The path that will handle the image file and throw them to the queue</span> +<span class="nx">app</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="s1">&#39;/upload&#39;</span><span class="p">,</span> <span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="kd">let</span> <span class="nx">img</span> <span class="o">=</span> <span class="nx">req</span><span class="p">.</span><span class="nx">files</span><span class="p">.</span><span class="nx">image</span><span class="p">;</span> <span class="c1">//&quot;image&quot; is the name of the input</span> + + <span class="nx">imagemin</span><span class="p">.</span><span class="nx">buffer</span><span class="p">(</span><span class="nx">img</span><span class="p">.</span><span class="nx">data</span><span class="p">,</span> <span class="p">{</span> + <span class="nx">plugins</span><span class="o">:</span> <span class="p">[</span><span class="nx">imageminPngquant</span><span class="p">()]</span> + <span class="p">})</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">out</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="nx">res</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="nx">out</span><span class="p">,</span><span class="s1">&#39;binary&#39;</span><span class="p">);</span> + <span class="nx">res</span><span class="p">.</span><span class="nx">end</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="s1">&#39;binary&#39;</span><span class="p">);</span> + <span class="p">});</span> +<span class="p">});</span> + + <span class="c1">//...</span> +</pre></div> +<p>Use <a class="reference external" href="https://www.getpostman.com/">Postman</a> to test the request. To see if it will work, make a request to <cite>http://localhost:4000/upload</cite> with a formdata with a file. Select the &quot;send and Download&quot; instead of &quot;Send&quot; and you should have an image after that. Bellow an image of how your postman should be.</p> +<img alt="Postman" src="/images/microservice_postman.png" /> +<p>That's it for today, next week we'll change our code to use RabbitMQ.</p> +Connecting to a database through SSH2018-03-29T10:03:00-03:002018-03-29T10:03:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-03-29:/connecting_to_database_through_ssh.html<p>If someday, for some reason, you need to establish a connection with a database which is behind a firewall and you only have SSH access on that server (and you don't want to use a CLI) you can do an SSH tunnel. It's pretty simple, bellow has a sample of …</p><p>If someday, for some reason, you need to establish a connection with a database which is behind a firewall and you only have SSH access on that server (and you don't want to use a CLI) you can do an SSH tunnel. It's pretty simple, bellow has a sample of how to allow connections to a remote Firebird database.</p> +<div class="highlight"><pre><span></span>ssh -L <span class="m">3051</span>:192.168.1.9:3050 username@192.168.1.9 +</pre></div> +<p>The <cite>-L</cite> parameter tells to SSH do a local port forwarding on local port <cite>3051</cite> to remote port <cite>3050</cite>. You can use it to a connection with many services, not just databases.</p> +<p>You can do the reverse kind of tunnel, forward connections from the host to your local machine, you just have to change the parameter form &quot;-L&quot; to &quot;-R&quot; and the port order is inverted, first come the port where the server will listen and after your localhost port. This remote port forwarding must be enabled on the server. Look for <cite>GatewayPorts</cite> at the ssh config file.</p> +<div class="highlight"><pre><span></span>ssh -R <span class="m">3050</span>:localhost:3050 username@192.168.1.9 +</pre></div> +<p>Why whould you need something like that?? Let's say you want to share a localhost site/database with a friend, but your internet connection don't allow you to expose any port but you have access to a remote server witch can do that. Problem solved ;).</p> +Now posting on Grepora2018-03-24T00:40:00-03:002018-03-24T00:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-03-24:/now_posting_on_grepora.html<p>A few weeks ago I started posting at <a class="reference external" href="https://grepora.com/blog/">Grepora</a> blog. If you like or are looking for some Oracle related stuff, Grepora it's a good place to go and spend a time reading :). From time to time I'll be posting there, it doesn't mean that this blog will be closed …</p><p>A few weeks ago I started posting at <a class="reference external" href="https://grepora.com/blog/">Grepora</a> blog. If you like or are looking for some Oracle related stuff, Grepora it's a good place to go and spend a time reading :). From time to time I'll be posting there, it doesn't mean that this blog will be closed or anything like that, but probably this one will be more focused on Front-end stuff, a few tricks with linux and a lil less with Java.</p> +Scaffolding a React app with Parcel and Yeoman2018-03-17T13:00:00-03:002018-03-17T13:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-03-17:/scaffolding_react_app_with_parcel_yeoman.html<p>Since <a class="reference external" href="https://parceljs.org/">Parcel JS</a> arrived, I've been using it a lot as an awesome alternative for WebPack. Webpack isn't bad but IMO it's too complex for the job and parcel do the same (at least the basic) with almost zero configuration. But if you need to create many apps (like a …</p><p>Since <a class="reference external" href="https://parceljs.org/">Parcel JS</a> arrived, I've been using it a lot as an awesome alternative for WebPack. Webpack isn't bad but IMO it's too complex for the job and parcel do the same (at least the basic) with almost zero configuration. But if you need to create many apps (like a react app) over and over again, it get's a lil boring following the basic steps.</p> +<div class="highlight"><pre><span></span>npm init -y +npm install --save react +npm install --save react-dom +npm install --save-dev parcel-bundler +npm install --save-dev babel-preset-env +npm install --save-dev babel-preset-react + +<span class="c1">#create .babelrc file</span> +<span class="c1">#create html, css, jsx files</span> + +parcel index.html +</pre></div> +<p>It's not a hard job, a simple shell script do the job, but what if you need some IFs when creating the app, or even change a few things at the <cite>package.json</cite>? A shell script still does the job, but come on... There is a better way. <a class="reference external" href="http://yeoman.io/">Yeoman</a> is here for you. I've already <a class="reference external" href="https://www.sipmann.com/desenvolvendo-app-firefoxos-pt.html">talked about it</a> on another post (Portuguese post).</p> +<p>Straight to the point, I've released a Yeoman generator to get the things a lil quicker. The name is <a class="reference external" href="https://www.npmjs.com/package/generator-parcel-react">generator-parcel-react</a> and it still lacks a few things that I will deal with soon. It's pretty simple to use it.</p> +<div class="highlight"><pre><span></span><span class="c1">#First time only</span> +npm install -g yo +npm install -g generator-parcel-react + +<span class="c1">#every time you create a new app</span> +yo parcel-react +</pre></div> +<p>And that's it. Right now you can scaffold and app with React, SASS and React Router. Hope you like it and feel free to ask new features.</p> +Could not open connection with MySQL and Hibernate2018-03-09T12:35:00-03:002018-03-09T12:35:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-03-09:/cloud-not-open-connection-java-mysql-hibernate.html<p>Last day I decided to deploy a MySQL Docker image to work with my Java application. I've been using PostgreSQL instead and have no problems at all, but after I moved to MySQL, the app didn't connect anymore with the database and throw some &quot;Could not open connection&quot; at my …</p><p>Last day I decided to deploy a MySQL Docker image to work with my Java application. I've been using PostgreSQL instead and have no problems at all, but after I moved to MySQL, the app didn't connect anymore with the database and throw some &quot;Could not open connection&quot; at my face, but why? I've tried to connect to it manually and got the same problem.</p> +<p>After some research, I found that the true error should be java.sql.SQLException: null, message from server: &quot;Host '172.17.0.4' is not allowed to connect to this MySQL server&quot; but it wasn't showing to me...</p> +<p>After all, be aware that with the docker image MySQL:5.7.21 (latest version right now) the root user isn't allowed to remote connect to the database (it's alright, security reasons) and if you still want to do remote connections to it with root there are a few things you can do.</p> +<ol class="arabic simple"> +<li>Create a user or allow root to access from other IPs.</li> +</ol> +<div class="highlight"><pre><span></span><span class="o">#</span><span class="k">No</span> <span class="k">access</span> <span class="k">to</span> <span class="k">user</span> <span class="n">root</span> <span class="k">on</span> <span class="k">any</span> <span class="n">other</span> <span class="n">IP</span> +<span class="k">SELECT</span> <span class="k">User</span><span class="p">,</span> <span class="k">Host</span> <span class="k">FROM</span> <span class="n">mysql</span><span class="p">.</span><span class="k">user</span><span class="p">;</span> +<span class="o">+</span><span class="c1">---------------+-----------+</span> +<span class="o">|</span> <span class="k">User</span> <span class="o">|</span> <span class="k">Host</span> <span class="o">|</span> +<span class="o">+</span><span class="c1">---------------+-----------+</span> +<span class="o">|</span> <span class="n">healthchecker</span> <span class="o">|</span> <span class="n">localhost</span> <span class="o">|</span> +<span class="o">|</span> <span class="n">root</span> <span class="o">|</span> <span class="n">localhost</span> <span class="o">|</span> +<span class="o">+</span><span class="c1">---------------+-----------+</span> +<span class="mi">2</span> <span class="k">rows</span> <span class="k">in</span> <span class="k">set</span> <span class="p">(</span><span class="mi">0</span><span class="p">.</span><span class="mi">01</span> <span class="n">sec</span><span class="p">)</span> + +<span class="k">CREATE</span> <span class="k">USER</span> <span class="s1">&#39;newuser&#39;</span><span class="o">@</span><span class="s1">&#39;%&#39;</span> <span class="n">IDENTIFIED</span> <span class="k">BY</span> <span class="s1">&#39;password&#39;</span><span class="p">;</span> <span class="o">#%</span> <span class="n">mean</span> <span class="k">any</span> <span class="n">IP</span> +<span class="k">GRANT</span> <span class="k">ALL</span> <span class="k">PRIVILEGES</span> <span class="k">ON</span> <span class="o">*</span><span class="p">.</span><span class="o">*</span> <span class="k">TO</span> <span class="s1">&#39;newuser&#39;</span><span class="o">@</span><span class="s1">&#39;%&#39;</span><span class="p">;</span> <span class="o">#*</span><span class="p">.</span><span class="o">*</span> <span class="n">mean</span> <span class="k">database</span><span class="p">.</span><span class="k">table</span> <span class="p">;)</span> +</pre></div> +<ol class="arabic simple" start="2"> +<li>Use MariaDB instead, witch come (at least on the version 10.2.13) with root allowed to do remote connections and will work like MySQL :)</li> +</ol> +<p>I changed to <a class="reference external" href="https://mariadb.org/">MariaDB</a> as it work without creating user or any changes on the Java code or the <cite>docker run command</cite>.</p> +Solving java.net.SocketException: Protocol family unavailable on a Java + Docker + WildFly2018-03-04T17:40:00-03:002018-03-04T17:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-03-04:/socketException-protocol-family-unavailable-java-docker-wildfly.html<p>On the last days I've been playing with <a class="reference external" href="http://wildfly-swarm.io/">WildFly Swarm</a> and I decided to deploy a simple app with Docker. Should work fine, at least that was what I thought. Built a container with the following Dockerfile and instead of a working web app, all that I got was the …</p><p>On the last days I've been playing with <a class="reference external" href="http://wildfly-swarm.io/">WildFly Swarm</a> and I decided to deploy a simple app with Docker. Should work fine, at least that was what I thought. Built a container with the following Dockerfile and instead of a working web app, all that I got was the error <cite>java.net.SocketException: Protocol family unavailable</cite>.</p> +<div class="highlight"><pre><span></span><span class="k">FROM</span> <span class="s">java:openjdk-8-jdk</span> + +<span class="k">COPY</span> target/issues.jar /opt/issues.jar + +<span class="k">EXPOSE</span><span class="s"> 8080</span> + +<span class="k">CMD</span> <span class="p">[</span><span class="s2">&quot;java&quot;</span><span class="p">,</span><span class="s2">&quot;-jar&quot;</span><span class="p">,</span><span class="s2">&quot;/opt/issues.jar&quot;</span><span class="p">]</span> +</pre></div> +<p>For some reason, WildFly and Java decided to use the IPv6 network interface from Docker instead the v4, so all you have to do is tell Java to prefer IPv4 instead with the following configuration option in your pom.xml file inside your WildFly plugin.</p> +<div class="highlight"><pre><span></span><span class="nt">&lt;plugin&gt;</span> + <span class="nt">&lt;groupId&gt;</span>org.wildfly.swarm<span class="nt">&lt;/groupId&gt;</span> + <span class="nt">&lt;artifactId&gt;</span>wildfly-swarm-plugin<span class="nt">&lt;/artifactId&gt;</span> + <span class="nt">&lt;version&gt;</span>2018.2.0<span class="nt">&lt;/version&gt;</span> + + <span class="c">&lt;!-- ADD THIS --&gt;</span> + <span class="nt">&lt;configuration&gt;</span> + <span class="nt">&lt;mainClass&gt;</span>org.wildfly.swarm.examples.netflix.ribbon.frontend.Main<span class="nt">&lt;/mainClass&gt;</span> + <span class="nt">&lt;properties&gt;</span> + <span class="nt">&lt;java.net.preferIPv4Stack&gt;</span>true<span class="nt">&lt;/java.net.preferIPv4Stack&gt;</span> + <span class="nt">&lt;/properties&gt;</span> + <span class="nt">&lt;/configuration&gt;</span> +</pre></div> +<p>Another way to solve is adding the same properties to the run command at the Dockerfile, so you choose where you'll add it. Bellow the Dockerfile solution.</p> +<div class="highlight"><pre><span></span><span class="k">FROM</span> <span class="s">java:openjdk-8-jdk</span> +<span class="k">ENV</span> <span class="nv">JAVA_OPTS</span><span class="o">=</span><span class="s2">&quot;-Djava.net.preferIPv4Stack=true -Djava.net.preferIPv4Addresses=true&quot;</span> + +<span class="k">COPY</span> target/issues.jar /opt/issues.jar + +<span class="k">EXPOSE</span><span class="s"> 8080</span> + +<span class="k">ENTRYPOINT</span> <span class="nb">exec</span> java <span class="nv">$JAVA_OPTS</span> -jar /opt/issues.jar +</pre></div> +Change display settings on linux with Disper2018-02-27T12:40:00-03:002018-02-27T12:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-02-27:/linux-external-display-with-disper.html<p>From time to time, I change the Linux distro on my laptop or just do a fresh install on it. And once in a while, have random problems with external displays. It can be something really &quot;simple&quot; like don't detecting the external monitor or something crazy like the image below …</p><p>From time to time, I change the Linux distro on my laptop or just do a fresh install on it. And once in a while, have random problems with external displays. It can be something really &quot;simple&quot; like don't detecting the external monitor or something crazy like the image below.</p> +<img alt="Display bug" src="/images/bug.png" /> +<p>As you can see at the image, the mint detected the display but mirrored it in a crazy way that works but doesn't at the same time. If you try anything and doesn't get working, or just wanna skip the whole job of configuring complexes text files, give a try to <a class="reference external" href="http://willem.engen.nl/projects/disper/">Disper</a>. Download the latest version. +Extract it on any folder, and make install it (on the extracted folder).</p> +<div class="highlight"><pre><span></span>make install +</pre></div> +<p>After that, you can start using it... There are a few options that will serve you well.</p> +<div class="highlight"><pre><span></span>disper -e <span class="c1">#extend your display</span> +</pre></div> +<div class="highlight"><pre><span></span>disper -c <span class="c1">#clone your display</span> +</pre></div> +<div class="highlight"><pre><span></span>disper -s <span class="c1">#only your external display</span> +</pre></div> +Java - Files.readAllBytes throws OutOfMemory2018-02-17T13:00:00-02:002018-02-17T13:00:00-02:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-02-17:/reading-files-java-readAllBytes-outofmemory.html<p>When you need to interact with files, there's the possibility to read all bytes from the file with <cite>Files.readAllBytes</cite>. But be aware of the kinds of files your application will deal with because the Java API files have a limit for the buffer that is defined as <cite>Integer.MAX_VALUE …</cite></p><p>When you need to interact with files, there's the possibility to read all bytes from the file with <cite>Files.readAllBytes</cite>. But be aware of the kinds of files your application will deal with because the Java API files have a limit for the buffer that is defined as <cite>Integer.MAX_VALUE</cite> as you can see above or at the OpenJDK sources.</p> +<div class="highlight"><pre><span></span><span class="kd">public</span> <span class="kd">static</span> <span class="kt">byte</span><span class="o">[]</span> <span class="nf">readAllBytes</span><span class="p">(</span><span class="n">Path</span> <span class="n">path</span><span class="p">)</span> <span class="kd">throws</span> <span class="n">IOException</span> <span class="p">{</span> + <span class="k">try</span> <span class="p">(</span><span class="n">FileChannel</span> <span class="n">fc</span> <span class="o">=</span> <span class="n">FileChannel</span><span class="p">.</span><span class="na">open</span><span class="p">(</span><span class="n">path</span><span class="p">))</span> <span class="p">{</span> + <span class="kt">long</span> <span class="n">size</span> <span class="o">=</span> <span class="n">fc</span><span class="p">.</span><span class="na">size</span><span class="p">();</span> + <span class="k">if</span> <span class="p">(</span><span class="n">size</span> <span class="o">&gt;</span> <span class="p">(</span><span class="kt">long</span><span class="p">)</span><span class="n">Integer</span><span class="p">.</span><span class="na">MAX_VALUE</span><span class="p">)</span> + <span class="k">throw</span> <span class="k">new</span> <span class="n">OutOfMemoryError</span><span class="p">(</span><span class="s">&quot;Required array size too large&quot;</span><span class="p">);</span> + + <span class="kt">byte</span><span class="o">[]</span> <span class="n">arr</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">byte</span><span class="o">[</span><span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">size</span><span class="o">]</span><span class="p">;</span> + <span class="n">ByteBuffer</span> <span class="n">bb</span> <span class="o">=</span> <span class="n">ByteBuffer</span><span class="p">.</span><span class="na">wrap</span><span class="p">(</span><span class="n">arr</span><span class="p">);</span> + <span class="k">while</span> <span class="p">(</span><span class="n">bb</span><span class="p">.</span><span class="na">hasRemaining</span><span class="p">())</span> <span class="p">{</span> + <span class="k">if</span> <span class="p">(</span><span class="n">fc</span><span class="p">.</span><span class="na">read</span><span class="p">(</span><span class="n">bb</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> + <span class="c1">// truncated</span> + <span class="k">break</span><span class="p">;</span> + <span class="p">}</span> + <span class="p">}</span> + + <span class="kt">int</span> <span class="n">nread</span> <span class="o">=</span> <span class="n">bb</span><span class="p">.</span><span class="na">position</span><span class="p">();</span> + <span class="k">return</span> <span class="p">(</span><span class="n">nread</span> <span class="o">==</span> <span class="n">size</span><span class="p">)</span> <span class="o">?</span> <span class="n">arr</span> <span class="p">:</span> <span class="n">Arrays</span><span class="p">.</span><span class="na">copyOf</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="n">nread</span><span class="p">);</span> + <span class="p">}</span> +<span class="p">}</span> +</pre></div> +<p>With that in mind, check if isn't better read chunks of bytes e work with that slice in exchange of loading the whole file into the memory ;). Above a simple example of how you can read chunks of bytes from the file.</p> +<div class="highlight"><pre><span></span><span class="kt">byte</span><span class="o">[]</span> <span class="n">buffer</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">byte</span><span class="o">[</span><span class="mi">1024</span><span class="o">]</span><span class="p">;</span> +<span class="n">FileInputStream</span> <span class="n">in</span> <span class="o">=</span> <span class="k">new</span> <span class="n">FileInputStream</span><span class="p">(</span><span class="n">file</span><span class="p">);</span> +<span class="kt">int</span> <span class="n">rc</span> <span class="o">=</span> <span class="n">in</span><span class="p">.</span><span class="na">read</span><span class="p">(</span><span class="n">buffer</span><span class="p">);</span> +<span class="k">while</span> <span class="p">(</span><span class="n">rc</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span> +<span class="p">{</span> + <span class="c1">//crazy stuff here with buffer</span> + <span class="n">rc</span> <span class="o">=</span> <span class="n">in</span><span class="p">.</span><span class="na">read</span><span class="p">(</span><span class="n">buffer</span><span class="p">);</span> +<span class="p">}</span> +</pre></div> + \ No newline at end of file diff --git a/feeds/all-en.atom.xml.gz b/feeds/all-en.atom.xml.gz new file mode 100644 index 000000000..7058dd7f4 Binary files /dev/null and b/feeds/all-en.atom.xml.gz differ diff --git a/feeds/all.atom.xml b/feeds/all.atom.xml new file mode 100644 index 000000000..a5c3528b0 --- /dev/null +++ b/feeds/all.atom.xml @@ -0,0 +1,1270 @@ + +Sipmannhttps://www.sipmann.com/2020-12-21T13:30:00-03:00Monitoring MySQL restarts with PowerShell2020-12-21T13:30:00-03:002020-12-21T13:30:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-12-21:/monitoring-mysql-restarts-with-powershell.html<p>Hey folks, it's time for another PowerShell script. If you haven't seen the other ones, check the links below.</p> +<ul> +<li><a href="https://www.sipmann.com/en/monitoring-mysql-replication-with-powershell.html">Monitoring MySQL replication with PowerShell</a></li> +</ul> +<p>Well, this one it's a pretty simple script, but again, if your customer doesn't have a Zabbix server or doesn't allow you to setup one to …</p><p>Hey folks, it's time for another PowerShell script. If you haven't seen the other ones, check the links below.</p> +<ul> +<li><a href="https://www.sipmann.com/en/monitoring-mysql-replication-with-powershell.html">Monitoring MySQL replication with PowerShell</a></li> +</ul> +<p>Well, this one it's a pretty simple script, but again, if your customer doesn't have a Zabbix server or doesn't allow you to setup one to do the monitoring, a set of scripts can be handy. We start executing some basic query <code>SHOW GLOBAL STATUS LIKE 'Uptime'</code>, with that we'll get exactly what we're looking for.</p> +<p>If for some reason, the command fails (watch for the "global" variable called <code>$lastExitCode</code>), we send an e-mail telling you about that connection problem.</p> +<p>And then, we get to the part where we parse the value, this one is pretty similar to the parse we did on the first post about using PowerShell to monitor MySQL. But we basically look for the Value line, split it by space and then parse the second position to an integer. And then all we have to do is check if the uptime is lower than our threshold, if it is we send an e-mail.</p> +<div class="highlight"><pre><span></span><code><span class="nv">$MailFrom</span> <span class="p">=</span> <span class="s1">&#39;maurio[at]sipmann.com&#39;</span> +<span class="nv">$MailTo</span> <span class="p">=</span> <span class="s1">&#39;mauricio[at]sipmann.com&#39;</span> +<span class="nv">$MysqlHost</span> <span class="p">=</span> <span class="s1">&#39;127.0.0.1&#39;</span> +<span class="nv">$MysqlUser</span> <span class="p">=</span> <span class="s1">&#39;root&#39;</span> +<span class="nv">$MysqlPass</span> <span class="p">=</span> <span class="s1">&#39;123&#39;</span> + + +<span class="nv">$data</span> <span class="p">=</span> <span class="p">$(</span><span class="n">mysql</span> <span class="n">-h</span> <span class="nv">$MysqlHost</span> <span class="n">-u</span> <span class="nv">$MysqlUser</span> <span class="n">-p</span><span class="s2">&quot;$MysqlPass&quot;</span> <span class="n">-e</span> <span class="s2">&quot;SHOW GLOBAL STATUS LIKE &#39;Uptime&#39; \G&quot;</span><span class="p">)</span> + +<span class="cm">&lt;# Unable to execute the sql Command #&gt;</span> +<span class="k">if</span> <span class="p">(</span><span class="nv">$lastExitCode</span> <span class="o">-eq</span> <span class="n">1</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Send-MailMessage</span> <span class="n">-To</span> <span class="nv">$MailTo</span> <span class="n">-From</span> <span class="nv">$MailFrom</span> <span class="n">-Subject</span> <span class="s1">&#39;Connection problem&#39;</span> <span class="n">-bodyAsHtml</span> <span class="s2">&quot;Connection problem on host ${MysqlHost}&quot;</span> <span class="n">-Credential</span> <span class="nb">Get-Credential</span> <span class="n">-SmtpServer</span> <span class="s1">&#39;smtp.office365.com&#39;</span> <span class="n">-Port</span> <span class="n">587</span> <span class="n">-UseSsl</span> + <span class="n">exit</span> +<span class="p">}</span> + +<span class="nv">$UpTime</span> <span class="p">=</span> <span class="no">[int]</span><span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Value:&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> + +<span class="cm">&lt;# If the uptime is lower then 20 minutes #&gt;</span> +<span class="k">if</span> <span class="p">(</span><span class="nv">$UpTime</span> <span class="o">-lt</span> <span class="n">1200</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Send-MailMessage</span> <span class="n">-To</span> <span class="nv">$MailTo</span> <span class="n">-From</span> <span class="nv">$MailFrom</span> <span class="n">-Subject</span> <span class="s2">&quot;MySQL Restarted&quot;</span> <span class="n">-bodyAsHtml</span> <span class="s2">&quot;MySQL host ${MysqlHost} restarted less than 20 minutes ago&quot;</span> <span class="n">-Credential</span> <span class="nb">Get-Credential</span> <span class="n">-SmtpServer</span> <span class="s1">&#39;smtp.office365.com&#39;</span> <span class="n">-Port</span> <span class="n">587</span> <span class="n">-UseSsl</span> +<span class="p">}</span> +</code></pre></div> + +<p>This script (and the other ones I use) is available at my GitHub <a href="https://github.com/sipmann/PowerShellScripts">here</a>. Keep in mind that the ones on the GitHub repo, are a little different from here.</p>Monitorando restarts do MySQL com PowerShell2020-12-21T13:30:00-03:002020-12-21T13:30:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-12-21:/pt/monitoring-mysql-restarts-with-powershell.html<p>Bom, chegou a hora para mais um script PowerShell. Se você ainda não viu os outros, de uma olhada no link abaixo.</p> +<ul> +<li><a href="https://www.sipmann.com/pt/monitoring-mysql-replication-with-powershell.html">Monitorando status de replicação do MySQL com PowerShell</a></li> +</ul> +<p>Este aqui é um script bem simples, mas novamente, se seu cliente não possui um servidor Zabbix ou não permite …</p><p>Bom, chegou a hora para mais um script PowerShell. Se você ainda não viu os outros, de uma olhada no link abaixo.</p> +<ul> +<li><a href="https://www.sipmann.com/pt/monitoring-mysql-replication-with-powershell.html">Monitorando status de replicação do MySQL com PowerShell</a></li> +</ul> +<p>Este aqui é um script bem simples, mas novamente, se seu cliente não possui um servidor Zabbix ou não permite que você configure um para realizar este monitoramento, um conjunto de scripts pode ser bem útil. Primeiramente nós executamos uma query báscia <code>SHOW GLOBAL STATUS LIKE 'Uptime'</code>, com ela nós conseguimos capturar exatamente o que nós estamos procurando.</p> +<p>Se por alguma razão o comando falhar (verificamos atravez da variábel global <code>$lastExitCode</code>), nós mandamos um e-mail lhe avisando sobre o problema ocorrido.</p> +<p>E então, nós chegamos à parte onde fazemos o parse do valor obtido, esta parte é bem similar ao parse que codificamos no primeiro post sobre monitoramento utilizando PowerShell. Nós basicamentes procuramos pela linha contendo <code>Value</code>, separamos por espaço e então parseamos a segunda posição em um inteiro. Então tudo que precisamos fazer é verificar se o valor parseado é menor que o nosso threshold, se for menor, nós mandamos um e-mail.</p> +<div class="highlight"><pre><span></span><code><span class="nv">$MailFrom</span> <span class="p">=</span> <span class="s1">&#39;maurio[at]sipmann.com&#39;</span> +<span class="nv">$MailTo</span> <span class="p">=</span> <span class="s1">&#39;mauricio[at]sipmann.com&#39;</span> +<span class="nv">$MysqlHost</span> <span class="p">=</span> <span class="s1">&#39;127.0.0.1&#39;</span> +<span class="nv">$MysqlUser</span> <span class="p">=</span> <span class="s1">&#39;root&#39;</span> +<span class="nv">$MysqlPass</span> <span class="p">=</span> <span class="s1">&#39;123&#39;</span> + + +<span class="nv">$data</span> <span class="p">=</span> <span class="p">$(</span><span class="n">mysql</span> <span class="n">-h</span> <span class="nv">$MysqlHost</span> <span class="n">-u</span> <span class="nv">$MysqlUser</span> <span class="n">-p</span><span class="s2">&quot;$MysqlPass&quot;</span> <span class="n">-e</span> <span class="s2">&quot;SHOW GLOBAL STATUS LIKE &#39;Uptime&#39; \G&quot;</span><span class="p">)</span> + +<span class="cm">&lt;# Unable to execute the sql Command #&gt;</span> +<span class="k">if</span> <span class="p">(</span><span class="nv">$lastExitCode</span> <span class="o">-eq</span> <span class="n">1</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Send-MailMessage</span> <span class="n">-To</span> <span class="nv">$MailTo</span> <span class="n">-From</span> <span class="nv">$MailFrom</span> <span class="n">-Subject</span> <span class="s1">&#39;Connection problem&#39;</span> <span class="n">-bodyAsHtml</span> <span class="s2">&quot;Connection problem on host ${MysqlHost}&quot;</span> <span class="n">-Credential</span> <span class="nb">Get-Credential</span> <span class="n">-SmtpServer</span> <span class="s1">&#39;smtp.office365.com&#39;</span> <span class="n">-Port</span> <span class="n">587</span> <span class="n">-UseSsl</span> + <span class="n">exit</span> +<span class="p">}</span> + +<span class="nv">$UpTime</span> <span class="p">=</span> <span class="no">[int]</span><span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Value:&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> + +<span class="cm">&lt;# If the uptime is lower then 20 minutes #&gt;</span> +<span class="k">if</span> <span class="p">(</span><span class="nv">$UpTime</span> <span class="o">-lt</span> <span class="n">1200</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Send-MailMessage</span> <span class="n">-To</span> <span class="nv">$MailTo</span> <span class="n">-From</span> <span class="nv">$MailFrom</span> <span class="n">-Subject</span> <span class="s2">&quot;MySQL Restarted&quot;</span> <span class="n">-bodyAsHtml</span> <span class="s2">&quot;MySQL host ${MysqlHost} restarted less than 20 minutes ago&quot;</span> <span class="n">-Credential</span> <span class="nb">Get-Credential</span> <span class="n">-SmtpServer</span> <span class="s1">&#39;smtp.office365.com&#39;</span> <span class="n">-Port</span> <span class="n">587</span> <span class="n">-UseSsl</span> +<span class="p">}</span> +</code></pre></div> + +<p>Este script (e os outros que eu utilizo) estão disponíveis no meu GitHub <a href="https://github.com/sipmann/PowerShellScripts">aqui</a>. Tenha em mente que os scripts localizados no GitHub, são um pouco diferentes do que exibido aqui. Espero que tenha achado útil.</p>Changing a MySQL user password across multiple application instances without downtime2020-12-09T13:40:00-03:002020-12-09T13:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-12-09:/mysql-dual-password-functionality.html<p>Do you need to change the password of a MySQL user that it's being used in an application, and can't allow a single downtime? Well, MySQL 8.0.14 came with a feature called <a href="https://dev.mysql.com/doc/refman/8.0/en/password-management.html#dual-passwords">Dual Password Support</a>, with it you can change the password keeping the previous password as a …</p><p>Do you need to change the password of a MySQL user that it's being used in an application, and can't allow a single downtime? Well, MySQL 8.0.14 came with a feature called <a href="https://dev.mysql.com/doc/refman/8.0/en/password-management.html#dual-passwords">Dual Password Support</a>, with it you can change the password keeping the previous password as a kind of backup. That way you still can log in using the old password or can start using the new one. With that, the password change workflow it's the following.</p> +<p>1) Change password keeping the old one;</p> +<p>2) Deploy the new config to your app/cluster;</p> +<p>3) Discard the old password.</p> +<p>To change the password and keep the old one, you have the following command.</p> +<div class="highlight"><pre><span></span><code><span class="k">ALTER</span> <span class="n">USER</span> <span class="s1">&#39;appuser&#39;</span><span class="o">@</span><span class="s1">&#39;localhost&#39;</span> <span class="n">IDENTIFIED</span> <span class="k">BY</span> <span class="s1">&#39;new_password&#39;</span> <span class="n">RETAIN</span> <span class="n">CURRENT</span> <span class="n">PASSWORD</span><span class="p">;</span> +</code></pre></div> + +<p>To discard the old one, run the following.</p> +<div class="highlight"><pre><span></span><code><span class="k">ALTER</span> <span class="n">USER</span> <span class="s1">&#39;appuser&#39;</span><span class="o">@</span><span class="s1">&#39;localhost&#39;</span> <span class="n">DISCARD</span> <span class="n">OLD</span> <span class="n">PASSWORD</span><span class="p">;</span> +</code></pre></div> + +<p>And you are done. Hope you find it as useful as I :)</p>Trocando a senha de um usuário do MySQL sem downtime da aplicação2020-12-09T13:40:00-03:002020-12-09T13:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-12-09:/pt/mysql-dual-password-functionality.html<p>Você deseja trocar a senha de um usuário do MySQL que está sendo utilizado por uma aplicação e não sofrer nenhum downtime? Bom, a versão 8.0.14 do MySQL foi liberada com uma feature chamada <a href="https://dev.mysql.com/doc/refman/8.0/en/password-management.html#dual-passwords">Dual Password Support</a>, com esta feature você pode alterar a senha de um usuário …</p><p>Você deseja trocar a senha de um usuário do MySQL que está sendo utilizado por uma aplicação e não sofrer nenhum downtime? Bom, a versão 8.0.14 do MySQL foi liberada com uma feature chamada <a href="https://dev.mysql.com/doc/refman/8.0/en/password-management.html#dual-passwords">Dual Password Support</a>, com esta feature você pode alterar a senha de um usuário mantendo a anterior ainda funcionando como uma forma de "backup". Desta forma, você ainda conseguirá autenticar com o usuário utilizando tanto a nova senha, quanto a anterior. Com isto, o seu processo de troca de senha fica algo como:</p> +<p>1) Troque a senha mantendo a anterior;</p> +<p>2) Faça o Deploy da nova configuração na sua aplicação/cluster;</p> +<p>3) Descarte a senha anterior.</p> +<p>Para alterar a senha mantendo a anterior, você deve rodar o seguinte comando:</p> +<div class="highlight"><pre><span></span><code><span class="k">ALTER</span> <span class="n">USER</span> <span class="s1">&#39;appuser&#39;</span><span class="o">@</span><span class="s1">&#39;localhost&#39;</span> <span class="n">IDENTIFIED</span> <span class="k">BY</span> <span class="s1">&#39;new_password&#39;</span> <span class="n">RETAIN</span> <span class="n">CURRENT</span> <span class="n">PASSWORD</span><span class="p">;</span> +</code></pre></div> + +<p>Para descartar a senha antiga, rode o seguinte:</p> +<div class="highlight"><pre><span></span><code><span class="k">ALTER</span> <span class="n">USER</span> <span class="s1">&#39;appuser&#39;</span><span class="o">@</span><span class="s1">&#39;localhost&#39;</span> <span class="n">DISCARD</span> <span class="n">OLD</span> <span class="n">PASSWORD</span><span class="p">;</span> +</code></pre></div> + +<p>E pronto. Espero que isto lhe ajude a evitar downtimes e dores de cabeça :)</p>Apache Nifi JSON to SQL Replacing underscore2020-12-02T14:00:00-03:002020-12-02T14:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-12-02:/apache-nifi-json-to-sql-replacing-underscore.html<p>Recently I was doing some ETL with Apache NiFi. But after a few minutes of drawing my flow, I saw that the component ConvertJSONToSQL was replacing the underscore ('_') from the field name in the where condition (I was preparing an Update SQL). That was weird because, at the set …</p><p>Recently I was doing some ETL with Apache NiFi. But after a few minutes of drawing my flow, I saw that the component ConvertJSONToSQL was replacing the underscore ('_') from the field name in the where condition (I was preparing an Update SQL). That was weird because, at the set statement, the field name was kept intact. After some research, I found that the property (see bellow) <code>Translate Field Names</code> was responsible for that weird replacement.</p> +<p><img alt="Apache NiFi JSONToSQL config" src="/images/apache_nifi_jsontosql.png"></p> +<p>Before setting it to <strong>FALSE</strong>, be aware that the properties on your JSON data must match exactly the name of your fields.</p>Apache Nifi JSON to SQL removendo underline2020-12-02T14:00:00-03:002020-12-02T14:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-12-02:/pt/apache-nifi-json-to-sql-replacing-underscore.html<p>Recentemente eu estava desenvolvendo alguns processos de ETL com o Apache NiFi. Mas após alguns minutos desenhando o meu fluxo, eu vi um comportamento estranho do componente ConvertJSONToSQL, que estava substituindo os underline ('_') do nome de um campo utilizado na condição da SQL (eu estava preparando um UPDATE). Aquilo …</p><p>Recentemente eu estava desenvolvendo alguns processos de ETL com o Apache NiFi. Mas após alguns minutos desenhando o meu fluxo, eu vi um comportamento estranho do componente ConvertJSONToSQL, que estava substituindo os underline ('_') do nome de um campo utilizado na condição da SQL (eu estava preparando um UPDATE). Aquilo estava estranho, uma vez que na definição do SET da SQL, o nome do campo permanecia inalterado. Depois de algumas pesquisas, achei uma doc que a propriedade (veja abaixo) <code>Translate Field Names</code> era a responsável por este comportamento estranho.</p> +<p><img alt="Apache NiFi JSONToSQL config" src="/images/apache_nifi_jsontosql.png"></p> +<p>Antes de definir a propriedade como <strong>FALSE</strong>, esteja ciente que as propriedades do seu JSON devem ser exatamente iguais aos nomes dos campos da sua tabela.</p>Blocking a user on SQL Server based on a schedule2020-11-14T07:00:00-03:002020-11-14T07:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-11-14:/blocking-user-on-sql-server-based-on-schedule.html<p>Ok, some time ago, I've posted about how you can set limits to connections on SQL Server using the <a href="https://www.sipmann.com/limiting-connection-resources-sql-server.html#.X6Cz8IhKhPY">Resource Governor</a>. But what if you can't use it? You always can block logins using a login trigger, but I don't like the idea of having selects running on every login …</p><p>Ok, some time ago, I've posted about how you can set limits to connections on SQL Server using the <a href="https://www.sipmann.com/limiting-connection-resources-sql-server.html#.X6Cz8IhKhPY">Resource Governor</a>. But what if you can't use it? You always can block logins using a login trigger, but I don't like the idea of having selects running on every login. So I came across with a solution using a stored procedure, a table and the Agent.</p> +<p>The main idea is, store the time that a user must be blocked and using the Agent, disable or enable the user. Bellow you can see the table (the table is in Portuguese, but I have a few comment blocks to help you).</p> +<div class="highlight"><pre><span></span><code><span class="k">CREATE</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"> </span><span class="p">(</span><span class="w"></span> +<span class="w"> </span><span class="n">Id</span><span class="w"> </span><span class="nc">INT</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">LoginName</span><span class="w"> </span><span class="nc">NVARCHAR</span><span class="p">(</span><span class="mi">100</span><span class="p">)</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">HrInicio</span><span class="w"> </span><span class="nc">TIME</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"> </span><span class="cm">/* Startint block time */</span><span class="w"></span> +<span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="nc">TIME</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"> </span><span class="cm">/* Ending block time */</span><span class="w"></span> +<span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="nc">INT</span><span class="w"> </span><span class="k">DEFAULT</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="cm">/* 0 = unblocked, 1 = blocked */</span><span class="w"></span> +<span class="w"> </span><span class="k">PRIMARY</span><span class="w"> </span><span class="k">KEY</span><span class="w"> </span><span class="p">(</span><span class="n">Id</span><span class="p">)</span><span class="w"></span> +<span class="p">);</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> + +<span class="cm">/* Don&#39;t block the SA user, precautions, you know */</span><span class="w"></span> +<span class="k">ALTER</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"></span> +<span class="w"> </span><span class="k">ADD</span><span class="w"> </span><span class="k">CONSTRAINT</span><span class="w"> </span><span class="n">chk_users</span><span class="w"> </span><span class="k">CHECK</span><span class="w"> </span><span class="p">(</span><span class="n">LoginName</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;sa&#39;</span><span class="p">));</span><span class="w"></span> + +<span class="k">ALTER</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"></span> +<span class="w"> </span><span class="k">ADD</span><span class="w"> </span><span class="k">CONSTRAINT</span><span class="w"> </span><span class="n">chk_hora_final_maior</span><span class="w"> </span><span class="k">CHECK</span><span class="w"> </span><span class="p">(</span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="n">HrInicio</span><span class="p">);</span><span class="w"></span> + +<span class="k">ALTER</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"></span> +<span class="w"> </span><span class="k">ADD</span><span class="w"> </span><span class="k">CONSTRAINT</span><span class="w"> </span><span class="n">chk_status_bloqueio</span><span class="w"> </span><span class="k">CHECK</span><span class="w"> </span><span class="p">(</span><span class="n">Bloqueado</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">));</span><span class="w"></span> + +<span class="k">CREATE</span><span class="w"> </span><span class="k">SEQUENCE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">seq_HorariosBloqueio</span><span class="w"> </span><span class="k">START</span><span class="w"> </span><span class="k">WITH</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="n">INCREMENT</span><span class="w"> </span><span class="k">BY</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +</code></pre></div> + +<p>After creating the table, let's check the procedure that will handle the enabling/disabling the users. Be aware that on the procedure, I've set the database name where the table was stored, you can change it replacing the <code>DBATOOLS</code> text to the database name where you created the table.</p> +<div class="highlight"><pre><span></span><code><span class="k">IF</span><span class="w"> </span><span class="nf">OBJECT_ID</span><span class="p">(</span><span class="s1">&#39;dbo.sp_ValidarLogin&#39;</span><span class="p">)</span><span class="w"> </span><span class="k">IS</span><span class="w"> </span><span class="k">NULL</span><span class="w"></span> +<span class="w"> </span><span class="k">EXEC</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;CREATE PROCEDURE dbo.sp_ValidarLogin AS RETURN 0;&#39;</span><span class="p">);</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> + +<span class="k">CREATE</span><span class="w"> </span><span class="ow">OR</span><span class="w"> </span><span class="k">ALTER</span><span class="w"> </span><span class="k">PROC</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">sp_ValidarLogin</span><span class="w"></span> +<span class="k">AS</span><span class="w"> </span><span class="k">BEGIN</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="nc">NVARCHAR</span><span class="p">(</span><span class="mi">100</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="nc">TIME</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="k">SET</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nf">CAST</span><span class="p">(</span><span class="nf">GETDATE</span><span class="p">()</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="nc">TIME</span><span class="p">);</span><span class="w"></span> + +<span class="w"> </span><span class="cm">/* Block the ones that aren&#39;t blocked already and maches the time */</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="n">block_cursor</span><span class="w"> </span><span class="nc">CURSOR</span><span class="w"></span> +<span class="w"> </span><span class="k">FOR</span><span class="w"> </span><span class="k">SELECT</span><span class="w"> </span><span class="n">LoginName</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&lt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&gt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"></span> +<span class="w"> </span><span class="k">OPEN</span><span class="w"> </span><span class="n">block_cursor</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">block_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> + +<span class="w"> </span><span class="k">WHILE</span><span class="w"> </span><span class="nb">@@FETCH_STATUS</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"></span> +<span class="w"> </span><span class="k">BEGIN</span><span class="w"></span> +<span class="w"> </span><span class="k">exec</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;ALTER LOGIN &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="s1">&#39; DISABLE;&#39;</span><span class="p">);</span><span class="w"></span> + +<span class="w"> </span><span class="k">print</span><span class="w"> </span><span class="s1">&#39;Bloqued usuario &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">block_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> +<span class="w"> </span><span class="k">END</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">CLOSE</span><span class="w"> </span><span class="n">block_cursor</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="k">DEALLOCATE</span><span class="w"> </span><span class="n">block_cursor</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">UPDATE</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">SET</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&lt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&gt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"></span> + + +<span class="w"> </span><span class="cm">/* Enable up who was blocked */</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="nc">CURSOR</span><span class="w"></span> +<span class="w"> </span><span class="k">FOR</span><span class="w"> </span><span class="k">SELECT</span><span class="w"> </span><span class="n">LoginName</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="p">(</span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">OR</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="p">)</span><span class="w"></span> +<span class="w"> </span><span class="k">OPEN</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> + +<span class="w"> </span><span class="k">WHILE</span><span class="w"> </span><span class="nb">@@FETCH_STATUS</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"></span> +<span class="w"> </span><span class="k">BEGIN</span><span class="w"></span> +<span class="w"> </span><span class="k">exec</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;ALTER LOGIN &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"> </span><span class="o">+</span><span class="s1">&#39; ENABLE;&#39;</span><span class="p">);</span><span class="w"></span> + +<span class="w"> </span><span class="k">print</span><span class="w"> </span><span class="s1">&#39;Unbloqued usuario &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> +<span class="w"> </span><span class="k">END</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">CLOSE</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="k">DEALLOCATE</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">UPDATE</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">SET</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="p">(</span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">OR</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="p">)</span><span class="w"></span> +<span class="k">END</span><span class="p">;</span><span class="w"></span> +</code></pre></div> + +<p>Ok, so now all you have to do, is schedule a job to run that stored procedure from minute to minute. Again, the main idea is tell the procedure when a user must be blocked and when it'll be unblocked. </p> +<div class="highlight"><pre><span></span><code><span class="err"> -- Will block the user protheus from 10 AM till 15 PM</span> +<span class="err"> INSERT INTO dbo.HorariosBloqueio (Id, LoginName, HrInicio, HrTermino) VALUES (NEXT VALUE FOR seq_HorariosBloqueio, &#39;protheus&#39;, &#39;10:00:00&#39;, &#39;15:00:00&#39;);</span> +</code></pre></div>Bloqueando um usuário do SQL Server baseado em uma tabela de horários2020-11-14T07:00:00-03:002020-11-14T07:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-11-14:/pt/blocking-user-on-sql-server-based-on-schedule.html<p>Ok, algum tempo atrás, eu postei sobre como você pode impor limites às conexões do SQL Server utilizando o <a href="https://www.sipmann.com/limiting-connection-resources-sql-server.html#.X6Cz8IhKhPY">Resource Governor</a>. Mas, e se você não pode utilizar ele? Você sempre pode bloquear logins usando uma trigger, mas eu não gosto da ideia de ter um select rodando a cada …</p><p>Ok, algum tempo atrás, eu postei sobre como você pode impor limites às conexões do SQL Server utilizando o <a href="https://www.sipmann.com/limiting-connection-resources-sql-server.html#.X6Cz8IhKhPY">Resource Governor</a>. Mas, e se você não pode utilizar ele? Você sempre pode bloquear logins usando uma trigger, mas eu não gosto da ideia de ter um select rodando a cada login. Então, eu cheguei a esta solução, utilizando uma stored procedure, uma tabela e o Agent.</p> +<p>A ideia principal é armazenar o horário em que um usuário deve ser bloqueado pelo Agent. Abaixo você pode ver a criação da tabela:</p> +<div class="highlight"><pre><span></span><code><span class="k">CREATE</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"> </span><span class="p">(</span><span class="w"></span> +<span class="w"> </span><span class="n">Id</span><span class="w"> </span><span class="nc">INT</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">LoginName</span><span class="w"> </span><span class="nc">NVARCHAR</span><span class="p">(</span><span class="mi">100</span><span class="p">)</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">HrInicio</span><span class="w"> </span><span class="nc">TIME</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"> </span><span class="cm">/* horário de inicio do bloqueio */</span><span class="w"></span> +<span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="nc">TIME</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"> </span><span class="cm">/*horário de termino */</span><span class="w"></span> +<span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="nc">INT</span><span class="w"> </span><span class="k">DEFAULT</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="cm">/* 0 = desbloqueado, 1 = bloqueado */</span><span class="w"></span> +<span class="w"> </span><span class="k">PRIMARY</span><span class="w"> </span><span class="k">KEY</span><span class="w"> </span><span class="p">(</span><span class="n">Id</span><span class="p">)</span><span class="w"></span> +<span class="p">);</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> + +<span class="cm">/* regra para Não bloquear o usuário SA */</span><span class="w"></span> +<span class="k">ALTER</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"></span> +<span class="w"> </span><span class="k">ADD</span><span class="w"> </span><span class="k">CONSTRAINT</span><span class="w"> </span><span class="n">chk_users</span><span class="w"> </span><span class="k">CHECK</span><span class="w"> </span><span class="p">(</span><span class="n">LoginName</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;sa&#39;</span><span class="p">));</span><span class="w"></span> + +<span class="k">ALTER</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"></span> +<span class="w"> </span><span class="k">ADD</span><span class="w"> </span><span class="k">CONSTRAINT</span><span class="w"> </span><span class="n">chk_hora_final_maior</span><span class="w"> </span><span class="k">CHECK</span><span class="w"> </span><span class="p">(</span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="n">HrInicio</span><span class="p">);</span><span class="w"></span> + +<span class="k">ALTER</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"></span> +<span class="w"> </span><span class="k">ADD</span><span class="w"> </span><span class="k">CONSTRAINT</span><span class="w"> </span><span class="n">chk_status_bloqueio</span><span class="w"> </span><span class="k">CHECK</span><span class="w"> </span><span class="p">(</span><span class="n">Bloqueado</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">));</span><span class="w"></span> + +<span class="k">CREATE</span><span class="w"> </span><span class="k">SEQUENCE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">seq_HorariosBloqueio</span><span class="w"> </span><span class="k">START</span><span class="w"> </span><span class="k">WITH</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="n">INCREMENT</span><span class="w"> </span><span class="k">BY</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +</code></pre></div> + +<p>Depois de criar a tabela, vamos verificar a procedure que vai fazer todo o trabalho de habilitar/desabilitar os usuários. Fique ciente que, nesta procedure, eu defini o nome do banco onde a tabela está armazenada. Você pode substituir o nome <code>DBATOOLS</code> pelo o nome da sua base.</p> +<div class="highlight"><pre><span></span><code><span class="k">IF</span><span class="w"> </span><span class="nf">OBJECT_ID</span><span class="p">(</span><span class="s1">&#39;dbo.sp_ValidarLogin&#39;</span><span class="p">)</span><span class="w"> </span><span class="k">IS</span><span class="w"> </span><span class="k">NULL</span><span class="w"></span> +<span class="w"> </span><span class="k">EXEC</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;CREATE PROCEDURE dbo.sp_ValidarLogin AS RETURN 0;&#39;</span><span class="p">);</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> + +<span class="k">CREATE</span><span class="w"> </span><span class="ow">OR</span><span class="w"> </span><span class="k">ALTER</span><span class="w"> </span><span class="k">PROC</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">sp_ValidarLogin</span><span class="w"></span> +<span class="k">AS</span><span class="w"> </span><span class="k">BEGIN</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="nc">NVARCHAR</span><span class="p">(</span><span class="mi">100</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="nc">TIME</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="k">SET</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nf">CAST</span><span class="p">(</span><span class="nf">GETDATE</span><span class="p">()</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="nc">TIME</span><span class="p">);</span><span class="w"></span> + +<span class="w"> </span><span class="cm">/* Bloqueia os que ainda não estiverem bloqueados de acordo com a hora atual */</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="n">block_cursor</span><span class="w"> </span><span class="nc">CURSOR</span><span class="w"></span> +<span class="w"> </span><span class="k">FOR</span><span class="w"> </span><span class="k">SELECT</span><span class="w"> </span><span class="n">LoginName</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&lt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&gt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"></span> +<span class="w"> </span><span class="k">OPEN</span><span class="w"> </span><span class="n">block_cursor</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">block_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> + +<span class="w"> </span><span class="k">WHILE</span><span class="w"> </span><span class="nb">@@FETCH_STATUS</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"></span> +<span class="w"> </span><span class="k">BEGIN</span><span class="w"></span> +<span class="w"> </span><span class="k">exec</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;ALTER LOGIN &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="s1">&#39; DISABLE;&#39;</span><span class="p">);</span><span class="w"></span> + +<span class="w"> </span><span class="k">print</span><span class="w"> </span><span class="s1">&#39;Bloqued usuario &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">block_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> +<span class="w"> </span><span class="k">END</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">CLOSE</span><span class="w"> </span><span class="n">block_cursor</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="k">DEALLOCATE</span><span class="w"> </span><span class="n">block_cursor</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">UPDATE</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">SET</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&lt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&gt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"></span> + + +<span class="w"> </span><span class="cm">/* Libera quem estava bloqueado */</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="nc">CURSOR</span><span class="w"></span> +<span class="w"> </span><span class="k">FOR</span><span class="w"> </span><span class="k">SELECT</span><span class="w"> </span><span class="n">LoginName</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="p">(</span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">OR</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="p">)</span><span class="w"></span> +<span class="w"> </span><span class="k">OPEN</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> + +<span class="w"> </span><span class="k">WHILE</span><span class="w"> </span><span class="nb">@@FETCH_STATUS</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"></span> +<span class="w"> </span><span class="k">BEGIN</span><span class="w"></span> +<span class="w"> </span><span class="k">exec</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;ALTER LOGIN &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"> </span><span class="o">+</span><span class="s1">&#39; ENABLE;&#39;</span><span class="p">);</span><span class="w"></span> + +<span class="w"> </span><span class="k">print</span><span class="w"> </span><span class="s1">&#39;Unbloqued usuario &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> +<span class="w"> </span><span class="k">END</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">CLOSE</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="k">DEALLOCATE</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">UPDATE</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">SET</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="p">(</span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">OR</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="p">)</span><span class="w"></span> +<span class="k">END</span><span class="p">;</span><span class="w"></span> +</code></pre></div> + +<p>Certo, então agora tudo que temos que fazer é definir o job no Agent para rodar a procedure de minuto em minuto. Novamente, a ideia principal é chamar a procedure quando um usuário deve ser bloqueado e quando deve ser desbloqueado.</p> +<div class="highlight"><pre><span></span><code><span class="err"> -- Vai bloquear o usuário protheus das 10 AM até 15 PM</span> +<span class="err"> INSERT INTO dbo.HorariosBloqueio (Id, LoginName, HrInicio, HrTermino) VALUES (NEXT VALUE FOR seq_HorariosBloqueio, &#39;protheus&#39;, &#39;10:00:00&#39;, &#39;15:00:00&#39;);</span> +</code></pre></div>How to set columns on select using Entity Framework2020-10-28T19:00:00-03:002020-10-28T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-28:/select_specific_fields_with_efcore.html<p>So, you use Entity Framework Core, and you usually code your selects like the following, maybe you are getting too much data.</p> +<div class="highlight"><pre><span></span><code><span class="kt">var</span> <span class="n">products</span> <span class="p">=</span> <span class="n">Products</span> + <span class="p">.</span><span class="n">Where</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span> <span class="p">&gt;</span> <span class="m">0</span><span class="p">)</span> + <span class="p">.</span><span class="n">OrderBy</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">)</span> + <span class="p">.</span><span class="n">ToList</span><span class="p">()</span> +</code></pre></div> + +<p>Running the query above, on my table, you'll get the following output, take a look …</p><p>So, you use Entity Framework Core, and you usually code your selects like the following, maybe you are getting too much data.</p> +<div class="highlight"><pre><span></span><code><span class="kt">var</span> <span class="n">products</span> <span class="p">=</span> <span class="n">Products</span> + <span class="p">.</span><span class="n">Where</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span> <span class="p">&gt;</span> <span class="m">0</span><span class="p">)</span> + <span class="p">.</span><span class="n">OrderBy</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">)</span> + <span class="p">.</span><span class="n">ToList</span><span class="p">()</span> +</code></pre></div> + +<p>Running the query above, on my table, you'll get the following output, take a look at how many columns you are getting back from your database.</p> +<p><img alt="Screenshot with every single column" src="/images/ef_core_allcolumns.png"></p> +<p>In my case, I only care about the Title, PublishedData, and a small description. So to get back only these fields, we have a few options. In the first one, we'll set the fields and return them as a dynamic object, the second one, is to give the .NET a class to use. </p> +<div class="highlight"><pre><span></span><code><span class="kt">var</span> <span class="n">products</span> <span class="p">=</span> <span class="n">Products</span> + + <span class="p">.</span><span class="n">Select</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="k">new</span> <span class="p">{</span><span class="n">p</span><span class="p">.</span><span class="n">ProductID</span><span class="p">,</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">,</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span><span class="p">,</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitPrice</span><span class="p">})</span> + <span class="c1">//.Select(p =&gt; new ProductDTO {p.ProductID, p.ProductName, p.UnitsInStock, p.UnitPrice})</span> + + <span class="p">.</span><span class="n">Where</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span> <span class="p">&gt;</span> <span class="m">0</span><span class="p">)</span> + <span class="p">.</span><span class="n">OrderBy</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">)</span> + <span class="p">.</span><span class="n">ToList</span><span class="p">()</span> +</code></pre></div> + +<p><img alt="Screenshot with fewer columns and also fewer data size" src="/images/ef_core_less_columns.png"></p>Como definir as colunas no select utilizando Entity Framework2020-10-28T19:00:00-03:002020-10-28T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-28:/pt/select_specific_fields_with_efcore.html<p>Então, você utiliza Entity Framework Core e geralmente faz o seu selecto da seguinte forma, talvez você está retornando muitos dados.</p> +<div class="highlight"><pre><span></span><code><span class="kt">var</span> <span class="n">products</span> <span class="p">=</span> <span class="n">Products</span> + <span class="p">.</span><span class="n">Where</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span> <span class="p">&gt;</span> <span class="m">0</span><span class="p">)</span> + <span class="p">.</span><span class="n">OrderBy</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">)</span> + <span class="p">.</span><span class="n">ToList</span><span class="p">()</span> +</code></pre></div> + +<p>Rodando a query acima, em uma base de testes você obtem o seguinte resultado, veja quantas …</p><p>Então, você utiliza Entity Framework Core e geralmente faz o seu selecto da seguinte forma, talvez você está retornando muitos dados.</p> +<div class="highlight"><pre><span></span><code><span class="kt">var</span> <span class="n">products</span> <span class="p">=</span> <span class="n">Products</span> + <span class="p">.</span><span class="n">Where</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span> <span class="p">&gt;</span> <span class="m">0</span><span class="p">)</span> + <span class="p">.</span><span class="n">OrderBy</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">)</span> + <span class="p">.</span><span class="n">ToList</span><span class="p">()</span> +</code></pre></div> + +<p>Rodando a query acima, em uma base de testes você obtem o seguinte resultado, veja quantas colunas estão retornando da sua base de dados.</p> +<p><img alt="Print com todas as colunas" src="/images/ef_core_allcolumns.png"></p> +<p>No meu caso, eu só pretendo ter de volta as colunas Title, PublishedData e uma pequena descrição. Então para selecionar apenas estes campos, nós temos algumas opções. Na primeira, nós vamos definir os campos e retornar um objeto do tipo Dynamic. A segunda forma, é dar ao .NET o objeto a ser retornado, pode ser por exêmplo um DTO.</p> +<div class="highlight"><pre><span></span><code><span class="kt">var</span> <span class="n">products</span> <span class="p">=</span> <span class="n">Products</span> + + <span class="p">.</span><span class="n">Select</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="k">new</span> <span class="p">{</span><span class="n">p</span><span class="p">.</span><span class="n">ProductID</span><span class="p">,</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">,</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span><span class="p">,</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitPrice</span><span class="p">})</span> + <span class="c1">//.Select(p =&gt; new ProductDTO {p.ProductID, p.ProductName, p.UnitsInStock, p.UnitPrice})</span> + + <span class="p">.</span><span class="n">Where</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span> <span class="p">&gt;</span> <span class="m">0</span><span class="p">)</span> + <span class="p">.</span><span class="n">OrderBy</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">)</span> + <span class="p">.</span><span class="n">ToList</span><span class="p">()</span> +</code></pre></div> + +<p><img alt="Print com menos colunas e também menor quantidade de dados" src="/images/ef_core_less_columns.png"></p>Zabbix Running on Low Memory Mode2020-10-20T19:00:00-03:002020-10-20T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-20:/zabbix-running-on-low-memory-mode.html<p>Hey folks, another Zabbix post today. This one it's about increasing the Zabbix Server Cache. It's pretty common (if you have the default settings only) get a warning about your <code>Zabbix value cache running on low memory mode</code> at your dashboard or logs.</p> +<p><img alt="Zabbix Dashboard warning about the memory problem" src="/images/zabbix_low_memory_mode.png"> +<img alt="Zabbix Dashboard cache graph 70% used" src="/images/zabbix_cache_filling.png"></p> +<p>To solve, go back to your Zabbix …</p><p>Hey folks, another Zabbix post today. This one it's about increasing the Zabbix Server Cache. It's pretty common (if you have the default settings only) get a warning about your <code>Zabbix value cache running on low memory mode</code> at your dashboard or logs.</p> +<p><img alt="Zabbix Dashboard warning about the memory problem" src="/images/zabbix_low_memory_mode.png"> +<img alt="Zabbix Dashboard cache graph 70% used" src="/images/zabbix_cache_filling.png"></p> +<p>To solve, go back to your Zabbix config file (<code>zabbix_server.conf</code>) and look for the tag <em>CacheSize</em>. Uncomment it and set to a value bigger than 8M (8M it's the default value). In my case, we set a cache of 100M. After the change, restart the service.</p> +<div class="highlight"><pre><span></span><code><span class="c1">### Option: CacheSize</span> +<span class="c1"># Size of configuration cache, in bytes.</span> +<span class="c1"># Shared memory size for storing host, item and trigger data.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 128K-64G</span> +<span class="c1"># Default:</span> +<span class="na">CacheSize</span><span class="o">=</span><span class="s">100M #uncomment this line</span> +</code></pre></div> + +<p><img alt="Zabbix Dashboard resolved memory problem" src="/images/zabbix_low_memory_solved.png"></p> +<p>See ya folks.</p>Zabbix Running on Low Memory Mode2020-10-20T19:00:00-03:002020-10-20T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-20:/pt/zabbix-running-on-low-memory-mode.html<p>Olá pessoal! Trago hoje outro post sobre Zabbix. Este é sobre aumentar o cache do seu Zabbix Server. É perfeitamente comum (se você roda com as configurações padrões) receber avisos sobre <code>Zabbix value cache running on low memory mode</code> no seu dashboard ou arquivos de log.</p> +<p><img alt="Zabbix Dashboard alertando sobre problemas de memória" src="/images/zabbix_low_memory_mode.png"> +<img alt="Zabbix Dashboard cache gráfico com 70% utilizado" src="/images/zabbix_cache_filling.png"></p> +<p>Para resolver, abra o …</p><p>Olá pessoal! Trago hoje outro post sobre Zabbix. Este é sobre aumentar o cache do seu Zabbix Server. É perfeitamente comum (se você roda com as configurações padrões) receber avisos sobre <code>Zabbix value cache running on low memory mode</code> no seu dashboard ou arquivos de log.</p> +<p><img alt="Zabbix Dashboard alertando sobre problemas de memória" src="/images/zabbix_low_memory_mode.png"> +<img alt="Zabbix Dashboard cache gráfico com 70% utilizado" src="/images/zabbix_cache_filling.png"></p> +<p>Para resolver, abra o seu arquivo de configuração (<code>zabbix_server.conf</code>) e procure pela tag <em>CacheSize</em>. Descomente a linha e defina um valor maior que 8M (8M é o valor padrão). No meu caso, nós configuramos um cache de 100M. Depois da troca, reinicie o serviço para que o mesmo tome efeito.</p> +<div class="highlight"><pre><span></span><code><span class="c1">### Option: CacheSize</span> +<span class="c1"># Size of configuration cache, in bytes.</span> +<span class="c1"># Shared memory size for storing host, item and trigger data.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 128K-64G</span> +<span class="c1"># Default:</span> +<span class="na">CacheSize</span><span class="o">=</span><span class="s">100M #Descomente esta linha</span> +</code></pre></div> + +<p><img alt="Zabbix Dashboard resolved memory problem" src="/images/zabbix_low_memory_solved.png"></p> +<p>Até breve.</p>Monitoring MySQL Replication Status with PowerShell2020-10-14T19:00:00-03:002020-10-14T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-14:/monitoring-mysql-replication-with-powershell.html<p>I've been migration some bash scripts that I have to PowerShell, and it's time to migrate a script that monitors the replication of a MySQL database. The credit for the original script goes to <a href="https://handyman.dulare.com/mysql-replication-status-alerts-with-bash-script/">Paweł</a>. It's a simple script where I seek a few tags/fields that we get from …</p><p>I've been migration some bash scripts that I have to PowerShell, and it's time to migrate a script that monitors the replication of a MySQL database. The credit for the original script goes to <a href="https://handyman.dulare.com/mysql-replication-status-alerts-with-bash-script/">Paweł</a>. It's a simple script where I seek a few tags/fields that we get from <code>SHOW SLAVE STATUS\G</code> command, the fields are. <code>Slave_IO_Running</code>, <code>Slave_SQL_Running</code>, and <code>Seconds_Behind_Master</code>. I still need to figure out the proper way to store/read variables like usernames and passwords, if you have any tips, feel free to even make a pull request (<a href="https://github.com/sipmann/PowerShellScripts">here</a>) at the git where I'll store some scripts.</p> +<div class="highlight"><pre><span></span><code><span class="cm">&lt;#</span> +<span class="cm"> Variables definition</span> +<span class="cm">#&gt;</span> +<span class="nv">$MaxSeconds</span> <span class="p">=</span> <span class="n">120</span> <span class="c"># Max seconds behind master allowed</span> +<span class="nv">$MysqlUser</span> <span class="p">=</span> <span class="s1">&#39;root&#39;</span> +<span class="nv">$MysqlPass</span> <span class="p">=</span> <span class="s1">&#39;&#39;</span> + +<span class="nv">$MailTo</span> <span class="p">=</span> <span class="s1">&#39;mauricio@sipmann.com&#39;</span> +<span class="nv">$MailFrom</span> <span class="p">=</span> <span class="s1">&#39;mauricio@sipmann.com&#39;</span> + + +<span class="nv">$data</span> <span class="p">=</span> <span class="p">$(</span><span class="n">mysql</span> <span class="n">-u</span> <span class="nv">$MysqlUser</span> <span class="n">-p</span><span class="s2">&quot;$MysqlPass&quot;</span> <span class="n">-e</span> <span class="s1">&#39;SHOW SLAVE STATUS \G&#39;</span><span class="p">)</span> + +<span class="c">#Debug data</span> +<span class="c">#$data = Get-Content &#39;c:\temp\sampleresult.txt&#39;</span> + +<span class="cm">&lt;# Parse the data #&gt;</span> +<span class="nv">$IORunning</span> <span class="p">=</span> <span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Slave_IO_Running:&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> +<span class="nv">$SQLRunning</span> <span class="p">=</span> <span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Slave_SQL_Running:&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> +<span class="nv">$LastErrNo</span> <span class="p">=</span> <span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Last_Errno&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> +<span class="nv">$SecondsBh</span> <span class="p">=</span> <span class="no">[int]</span><span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Seconds_Behind_Master&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> + +<span class="k">If</span> <span class="p">(</span><span class="nv">$IORunning</span> <span class="o">-Eq</span> <span class="s1">&#39;No&#39;</span> <span class="o">-Or</span> <span class="nv">$SQLRunning</span> <span class="o">-Eq</span> <span class="s1">&#39;No&#39;</span> <span class="o">-Or</span> <span class="nv">$SecondsBh</span> <span class="o">-gt</span> <span class="nv">$MaxSeconds</span><span class="p">)</span> <span class="p">{</span> + <span class="nv">$MailBody</span> <span class="p">=</span> <span class="s1">&#39;&lt;h1&gt;Problema na replicação&lt;/h1&gt;&lt;br&gt;&#39;</span> + + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39; IO Running: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$IORunning</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39; SQL Running: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$SQLRunning</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39;Seconds Behind: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$SecondsBh</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39; Last Err No: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$LastErrNo</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + + <span class="cm">&lt;# Send e-mail, maybe some telegram message here too #&gt;</span> + <span class="nb">Send-MailMessage</span> <span class="n">-To</span> <span class="nv">$MailTo</span> <span class="n">-From</span> <span class="nv">$MailFrom</span> <span class="n">-Subject</span> <span class="s1">&#39;Problemas na replicação&#39;</span> <span class="n">-bodyAsHtml</span> <span class="nv">$MailBody</span> <span class="n">-Credential</span> <span class="p">(</span><span class="nb">Get-Credential</span><span class="p">)</span> <span class="n">-SmtpServer</span> <span class="s1">&#39;smtp.office365.com&#39;</span> <span class="n">-Port</span> <span class="n">587</span> <span class="n">-UseSsl</span> +<span class="p">}</span> <span class="k">Else</span> <span class="p">{</span> + <span class="nb">Write-Host</span> <span class="s2">&quot;Up and running&quot;</span> +<span class="p">}</span> +</code></pre></div>Monitorando status de replicação do MySQL com PowerShell2020-10-14T19:00:00-03:002020-10-14T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-14:/pt/monitoring-mysql-replication-with-powershell.html<p>Tenho migrado alguns scripts bash que tenho para PowerShell, e chegou a vez de migrar um script de monitoramento de replicação do MySQL. Fica como crédito o script original do <a href="https://handyman.dulare.com/mysql-replication-status-alerts-with-bash-script/">Paweł</a>. É um script bem simples onde eu verifico algumas tags resultantes do <code>SHOW SLAVE STATUS\G</code>, são elas. <code>Slave_IO_Running …</code></p><p>Tenho migrado alguns scripts bash que tenho para PowerShell, e chegou a vez de migrar um script de monitoramento de replicação do MySQL. Fica como crédito o script original do <a href="https://handyman.dulare.com/mysql-replication-status-alerts-with-bash-script/">Paweł</a>. É um script bem simples onde eu verifico algumas tags resultantes do <code>SHOW SLAVE STATUS\G</code>, são elas. <code>Slave_IO_Running</code>, <code>Slave_SQL_Running</code> e <code>Seconds_Behind_Master</code>. Ainda preciso verificar formas mais corretas de armazenar/carregar as variáveis como usuários e senha, se tiver alguma dica, fique à vontade para inclusive fazer um pull request (<a href="https://github.com/sipmann/PowerShellScripts">aqui</a>) no repositório onde vou armazenar alguns dos meus scripts.</p> +<div class="highlight"><pre><span></span><code><span class="cm">&lt;#</span> +<span class="cm"> Variables definition</span> +<span class="cm">#&gt;</span> +<span class="nv">$MaxSeconds</span> <span class="p">=</span> <span class="n">120</span> <span class="c"># Max seconds behind master allowed</span> +<span class="nv">$MysqlUser</span> <span class="p">=</span> <span class="s1">&#39;root&#39;</span> +<span class="nv">$MysqlPass</span> <span class="p">=</span> <span class="s1">&#39;&#39;</span> + +<span class="nv">$MailTo</span> <span class="p">=</span> <span class="s1">&#39;mauricio@sipmann.com&#39;</span> +<span class="nv">$MailFrom</span> <span class="p">=</span> <span class="s1">&#39;mauricio@sipmann.com&#39;</span> + + +<span class="nv">$data</span> <span class="p">=</span> <span class="p">$(</span><span class="n">mysql</span> <span class="n">-u</span> <span class="nv">$MysqlUser</span> <span class="n">-p</span><span class="s2">&quot;$MysqlPass&quot;</span> <span class="n">-e</span> <span class="s1">&#39;SHOW SLAVE STATUS \G&#39;</span><span class="p">)</span> + +<span class="c">#Debug data</span> +<span class="c">#$data = Get-Content &#39;c:\temp\sampleresult.txt&#39;</span> + +<span class="cm">&lt;# Parse the data #&gt;</span> +<span class="nv">$IORunning</span> <span class="p">=</span> <span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Slave_IO_Running:&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> +<span class="nv">$SQLRunning</span> <span class="p">=</span> <span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Slave_SQL_Running:&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> +<span class="nv">$LastErrNo</span> <span class="p">=</span> <span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Last_Errno&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> +<span class="nv">$SecondsBh</span> <span class="p">=</span> <span class="no">[int]</span><span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Seconds_Behind_Master&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> + +<span class="k">If</span> <span class="p">(</span><span class="nv">$IORunning</span> <span class="o">-Eq</span> <span class="s1">&#39;No&#39;</span> <span class="o">-Or</span> <span class="nv">$SQLRunning</span> <span class="o">-Eq</span> <span class="s1">&#39;No&#39;</span> <span class="o">-Or</span> <span class="nv">$SecondsBh</span> <span class="o">-gt</span> <span class="nv">$MaxSeconds</span><span class="p">)</span> <span class="p">{</span> + <span class="nv">$MailBody</span> <span class="p">=</span> <span class="s1">&#39;&lt;h1&gt;Problema na replicação&lt;/h1&gt;&lt;br&gt;&#39;</span> + + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39; IO Running: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$IORunning</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39; SQL Running: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$SQLRunning</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39;Seconds Behind: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$SecondsBh</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39; Last Err No: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$LastErrNo</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + + <span class="cm">&lt;# Send e-mail, maybe some telegram message here too #&gt;</span> + <span class="nb">Send-MailMessage</span> <span class="n">-To</span> <span class="nv">$MailTo</span> <span class="n">-From</span> <span class="nv">$MailFrom</span> <span class="n">-Subject</span> <span class="s1">&#39;Problemas na replicação&#39;</span> <span class="n">-bodyAsHtml</span> <span class="nv">$MailBody</span> <span class="n">-Credential</span> <span class="p">(</span><span class="nb">Get-Credential</span><span class="p">)</span> <span class="n">-SmtpServer</span> <span class="s1">&#39;smtp.office365.com&#39;</span> <span class="n">-Port</span> <span class="n">587</span> <span class="n">-UseSsl</span> +<span class="p">}</span> <span class="k">Else</span> <span class="p">{</span> + <span class="nb">Write-Host</span> <span class="s2">&quot;Up and running&quot;</span> +<span class="p">}</span> +</code></pre></div>Microsoft Against Covid2020-10-03T19:00:00-03:002020-10-03T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-03:/microsoft-against-covid.html<p>Has your job been affected by covid? Well, last week I've posted on <a href="https://grepora.com/2020/09/17/microsoft-ignite-certification-voucher/">Grepora</a> about a Free Certification Voucher that Microsoft was giving away at the Microsoft Ignite event. After that, I found that they were also giving a huge discount to people who have had their job affected by …</p><p>Has your job been affected by covid? Well, last week I've posted on <a href="https://grepora.com/2020/09/17/microsoft-ignite-certification-voucher/">Grepora</a> about a Free Certification Voucher that Microsoft was giving away at the Microsoft Ignite event. After that, I found that they were also giving a huge discount to people who have had their job affected by covid pandemic. </p> +<p>To see more details about if you were eligible, access <a href="https://docs.microsoft.com/en-us/learn/certifications/skillingoffer">https://docs.microsoft.com/en-us/learn/certifications/skillingoffer</a>.</p>Microsoft Contra Covid2020-10-03T19:00:00-03:002020-10-03T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-03:/pt/microsoft-against-covid.html<p>Você teve seu trabalho afetado pela pandemia do covid? Bom, na última semana eu postei no <a href="https://grepora.com/2020/09/17/microsoft-ignite-certification-voucher/">Grepora</a> sobre um Voucher para certificação gratuita que a Microsoft estava distribuindo durante o evento Microsoft Ignite. Depois disto, eu fiquei sabendo que eles também estão entregando grandes discontos para quem teve o seu …</p><p>Você teve seu trabalho afetado pela pandemia do covid? Bom, na última semana eu postei no <a href="https://grepora.com/2020/09/17/microsoft-ignite-certification-voucher/">Grepora</a> sobre um Voucher para certificação gratuita que a Microsoft estava distribuindo durante o evento Microsoft Ignite. Depois disto, eu fiquei sabendo que eles também estão entregando grandes discontos para quem teve o seu trabalho afetado pela pandemia do covid. </p> +<p>Para saber se você pode receber este desconto, acesse <a href="https://docs.microsoft.com/en-us/learn/certifications/skillingoffer">https://docs.microsoft.com/en-us/learn/certifications/skillingoffer</a>.</p>The power of PowerShell2020-09-21T19:00:00-03:002020-09-21T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-09-21:/the-power-of-powershell.html<p>As a long time Linux user, I've automated a few things with bash scripts and stayed away from PowerShell... I've moved to a Windows environment a few years ago and still, haven gave a shot to PS. But why not? I've made a few scripts to automate some tasks at …</p><p>As a long time Linux user, I've automated a few things with bash scripts and stayed away from PowerShell... I've moved to a Windows environment a few years ago and still, haven gave a shot to PS. But why not? I've made a few scripts to automate some tasks at a Protheus server.</p> +<p>I found the PS scripts being easy to read and understand. Bellow, we have a script to remove files filtering their extension (or no extension at all like the following script). </p> +<div class="highlight"><pre><span></span><code><span class="nb">Get-ChildItem</span> <span class="s2">&quot;C:\TOTVS\protheus_data\system&quot;</span> <span class="o">-File</span> <span class="n">-Filter</span> <span class="p">*.</span> <span class="p">|</span> <span class="nb">Move-Item</span> <span class="n">-Force</span> <span class="n">-Destination</span> <span class="p">{</span> + <span class="cm">&lt;# Diretory where the files will be moved. You can use Date formats to help name it #&gt;</span> + <span class="cm">&lt;# LastWriteTime proprtie from the current file #&gt;</span> + <span class="nv">$dir</span> <span class="p">=</span> <span class="s2">&quot;C:\bad_files\{0:yyyy\\MM\\dd}&quot;</span> <span class="o">-f</span> <span class="nv">$_</span><span class="p">.</span><span class="n">LastWriteTime</span> + <span class="nv">$null</span> <span class="p">=</span> <span class="n">mkdir</span> <span class="nv">$dir</span> <span class="n">-Force</span> + <span class="s2">&quot;$dir\</span><span class="p">$(</span><span class="nv">$_</span><span class="p">.</span><span class="n">Name</span><span class="p">)</span><span class="s2">&quot;</span> +<span class="p">}</span> +</code></pre></div> + +<p>Have you ever been in the need to remove files based on other file content? Bello a script where I read a file that has the names of files that I want to remove. </p> +<div class="highlight"><pre><span></span><code><span class="k">foreach</span><span class="p">(</span><span class="nv">$line</span> <span class="k">in</span> <span class="nb">Get-Content</span> <span class="p">.\</span><span class="n">Desktop</span><span class="p">\</span><span class="n">bad_files</span><span class="p">.</span><span class="n">txt</span><span class="p">)</span> <span class="p">{</span> + <span class="k">if</span> <span class="p">(</span><span class="nb">Test-Path</span><span class="p">(</span><span class="s1">&#39;\\x.y.z.a\c$\TOTVS\protheus_data\xmls\&#39;</span><span class="p">+</span><span class="nv">$line</span><span class="p">+</span><span class="s1">&#39;.xml&#39;</span><span class="p">))</span> <span class="p">{</span> + <span class="nb">Remove-Item</span><span class="p">(</span><span class="s1">&#39;\\x.y.z.a\c$\TOTVS\protheus_data\xmls\&#39;</span><span class="p">+</span><span class="nv">$line</span><span class="p">+</span><span class="s1">&#39;.xml&#39;</span><span class="p">)</span> + <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> + <span class="nb">echo </span><span class="nv">$line</span> <span class="p">+</span> <span class="s1">&#39; - File not found&#39;</span> + <span class="p">}</span> +<span class="p">}</span> +</code></pre></div> + +<p>And a bonus script to stop/start services (if you handle some Protheus Server, you know why I do that).</p> +<div class="highlight"><pre><span></span><code><span class="nv">$servicesNames</span> <span class="p">=</span> <span class="s1">&#39;app_main&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker1&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker2&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker3&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker4&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker5&#39;</span> + +<span class="nb">Write-host</span> <span class="s2">&quot;Stoping Services&quot;</span> +<span class="nb">Write-host</span> <span class="s2">&quot;--------------------------&quot;</span> + +<span class="k">foreach</span> <span class="p">(</span><span class="nv">$srv</span> <span class="k">in</span> <span class="nv">$servicesNames</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Write-host</span> <span class="s2">&quot;Stopping: &quot;</span> <span class="p">+</span> <span class="nv">$srv</span> + <span class="nv">$SrvPID</span> <span class="p">=</span> <span class="p">(</span><span class="nb">get-wmiobject</span> <span class="n">win32_service</span> <span class="p">|</span> <span class="nb">where </span><span class="p">{</span> <span class="nv">$_</span><span class="p">.</span><span class="n">name</span> <span class="o">-eq</span> <span class="nv">$srv</span><span class="p">}).</span><span class="n">processID</span> + <span class="nb">Write-host</span> <span class="s2">&quot;PID: &quot;</span> <span class="p">+</span> <span class="nv">$SrvPID</span> + + <span class="cm">&lt;# Force if the proccess is stucked #&gt;</span> + <span class="nb">Stop-Process</span> <span class="nv">$SrvPID</span> <span class="n">-Force</span> + <span class="nb">Write-host</span> <span class="s2">&quot;PDI &quot;</span> <span class="p">+</span> <span class="nv">$SrvPID</span> <span class="p">+</span> <span class="s2">&quot; stopped&quot;</span> +<span class="p">}</span> + + +<span class="nb">Write-host</span> <span class="s2">&quot;Starting Services&quot;</span> +<span class="nb">Write-host</span> <span class="s2">&quot;--------------------------&quot;</span> + +<span class="k">foreach</span> <span class="p">(</span><span class="nv">$srv</span> <span class="k">in</span> <span class="nv">$servicesNames</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Write-host</span> <span class="s2">&quot;Starting: &quot;</span> <span class="p">+</span> <span class="nv">$srv</span> + <span class="nb">Start-Service</span> <span class="nv">$srv</span> +<span class="p">}</span> +</code></pre></div> + +<p>Do you have any automated script? Share with us :)</p>O poder do PowerShell2020-09-21T19:00:00-03:002020-09-21T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-09-21:/pt/the-power-of-powershell.html<p>Como um usuário linux por muito tempo, eu automatizei algumas tarefas com scripts bash e fiquei longe do PowerShell... Voltei a utilizar Windows alguns anos atrás e ainda assim, não dei uma chance ao PS. Mas porque não? Eu fiz alguns scripts para automatizar algumas tarefas em um servidor Protheus …</p><p>Como um usuário linux por muito tempo, eu automatizei algumas tarefas com scripts bash e fiquei longe do PowerShell... Voltei a utilizar Windows alguns anos atrás e ainda assim, não dei uma chance ao PS. Mas porque não? Eu fiz alguns scripts para automatizar algumas tarefas em um servidor Protheus.</p> +<p>Eu acabei achando os scripts PS de fácil leitura e entendimento. Abaixo, nós temos um script para remover arquivos filtrando pela sua extensão (ou sem extensão alguma no caso do script em questão).</p> +<div class="highlight"><pre><span></span><code><span class="nb">Get-ChildItem</span> <span class="s2">&quot;C:\TOTVS\protheus_data\system&quot;</span> <span class="o">-File</span> <span class="n">-Filter</span> <span class="p">*.</span> <span class="p">|</span> <span class="nb">Move-Item</span> <span class="n">-Force</span> <span class="n">-Destination</span> <span class="p">{</span> + <span class="cm">&lt;# Diretório ao qual os arquivos vão ser movidos. Você pode utilizar formatos de data para nomear os diretórios #&gt;</span> + <span class="cm">&lt;# LastWriteTime é a propriedade do arquivo corrent #&gt;</span> + <span class="nv">$dir</span> <span class="p">=</span> <span class="s2">&quot;C:\bad_files\{0:yyyy\\MM\\dd}&quot;</span> <span class="o">-f</span> <span class="nv">$_</span><span class="p">.</span><span class="n">LastWriteTime</span> + <span class="nv">$null</span> <span class="p">=</span> <span class="n">mkdir</span> <span class="nv">$dir</span> <span class="n">-Force</span> + <span class="s2">&quot;$dir\</span><span class="p">$(</span><span class="nv">$_</span><span class="p">.</span><span class="n">Name</span><span class="p">)</span><span class="s2">&quot;</span> +<span class="p">}</span> +</code></pre></div> + +<p>Você já precisou remover arquivos baseado no conteúdo de outro arquivo? Abaixo um script onde eu leio um arquivo que contem os nomes de arquivos que eu desejo remover. </p> +<div class="highlight"><pre><span></span><code><span class="k">foreach</span><span class="p">(</span><span class="nv">$line</span> <span class="k">in</span> <span class="nb">Get-Content</span> <span class="p">.\</span><span class="n">Desktop</span><span class="p">\</span><span class="n">bad_files</span><span class="p">.</span><span class="n">txt</span><span class="p">)</span> <span class="p">{</span> + <span class="k">if</span> <span class="p">(</span><span class="nb">Test-Path</span><span class="p">(</span><span class="s1">&#39;\\x.y.z.a\c$\TOTVS\protheus_data\xmls\&#39;</span><span class="p">+</span><span class="nv">$line</span><span class="p">+</span><span class="s1">&#39;.xml&#39;</span><span class="p">))</span> <span class="p">{</span> + <span class="nb">Remove-Item</span><span class="p">(</span><span class="s1">&#39;\\x.y.z.a\c$\TOTVS\protheus_data\xmls\&#39;</span><span class="p">+</span><span class="nv">$line</span><span class="p">+</span><span class="s1">&#39;.xml&#39;</span><span class="p">)</span> + <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> + <span class="nb">echo </span><span class="nv">$line</span> <span class="p">+</span> <span class="s1">&#39; - File not found&#39;</span> + <span class="p">}</span> +<span class="p">}</span> +</code></pre></div> + +<p>E um script bonus para parar e iniciar serviços (se você gerencia um servidor Protheus, você sabe o porque eu faço isto).</p> +<div class="highlight"><pre><span></span><code><span class="nv">$servicesNames</span> <span class="p">=</span> <span class="s1">&#39;app_main&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker1&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker2&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker3&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker4&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker5&#39;</span> + +<span class="nb">Write-host</span> <span class="s2">&quot;Parando Serviços&quot;</span> +<span class="nb">Write-host</span> <span class="s2">&quot;--------------------------&quot;</span> + +<span class="k">foreach</span> <span class="p">(</span><span class="nv">$srv</span> <span class="k">in</span> <span class="nv">$servicesNames</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Write-host</span> <span class="s2">&quot;Parando: &quot;</span> <span class="p">+</span> <span class="nv">$srv</span> + <span class="nv">$SrvPID</span> <span class="p">=</span> <span class="p">(</span><span class="nb">get-wmiobject</span> <span class="n">win32_service</span> <span class="p">|</span> <span class="nb">where </span><span class="p">{</span> <span class="nv">$_</span><span class="p">.</span><span class="n">name</span> <span class="o">-eq</span> <span class="nv">$srv</span><span class="p">}).</span><span class="n">processID</span> + <span class="nb">Write-host</span> <span class="s2">&quot;PID: &quot;</span> <span class="p">+</span> <span class="nv">$SrvPID</span> + + <span class="cm">&lt;# Força a parada caso o serviço esteja travado #&gt;</span> + <span class="nb">Stop-Process</span> <span class="nv">$ServicePID</span> <span class="n">-Force</span> + <span class="nb">Write-host</span> <span class="s2">&quot;PDI &quot;</span> <span class="p">+</span> <span class="nv">$SrvPID</span> <span class="p">+</span> <span class="s2">&quot; parado&quot;</span> +<span class="p">}</span> + + +<span class="nb">Write-host</span> <span class="s2">&quot;Inicializando Serviços&quot;</span> +<span class="nb">Write-host</span> <span class="s2">&quot;--------------------------&quot;</span> + +<span class="k">foreach</span> <span class="p">(</span><span class="nv">$srv</span> <span class="k">in</span> <span class="nv">$servicesNames</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Write-host</span> <span class="s2">&quot;Inicializando: &quot;</span> <span class="p">+</span> <span class="nv">$srv</span> + <span class="nb">Start-Service</span> <span class="nv">$srv</span> +<span class="p">}</span> +</code></pre></div> + +<p>Você tem algum script de automação? Compartilhe conosco :)</p>Top Level Statement in C# 92020-07-29T19:00:00-03:002020-07-29T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-07-29:/top_level_statement_csharp_9.html<p>Hey folks, I'm coming along to tell you a few things about the new feature of C# 9. Every time you want to start a new project, you always have the same Main File, with the same structure. At the next version of C# (version 9), we'll have a new …</p><p>Hey folks, I'm coming along to tell you a few things about the new feature of C# 9. Every time you want to start a new project, you always have the same Main File, with the same structure. At the next version of C# (version 9), we'll have a new feature called <code>Top Level Statement</code>. With that, we'll be able to code our app without any namespace/class/public void static main structure. Take a look at the code below.</p> +<div class="highlight"><pre><span></span><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span> + +<span class="n">Console</span><span class="p">.</span><span class="n">WriteLine</span><span class="p">(</span><span class="s">&quot;Hello World!&quot;</span><span class="p">);</span> +</code></pre></div> + +<p>It looks pretty simple, but with this, you can play around with your code, and even code a simple/tiny Web API. To start playing with the new features, firstly download the <a href="https://dotnet.microsoft.com/download/dotnet/5.0">.net 5 SDK</a> and change your <code>.csproj</code> file to target the .net 5 and language preview like bellow.</p> +<div class="highlight"><pre><span></span><code><span class="nt">&lt;Project</span> <span class="na">Sdk=</span><span class="s">&quot;Microsoft.NET.Sdk&quot;</span><span class="nt">&gt;</span> + <span class="nt">&lt;PropertyGroup&gt;</span> + <span class="nt">&lt;OutputType&gt;</span>Exe<span class="nt">&lt;/OutputType&gt;</span> + <span class="nt">&lt;TargetFramework&gt;</span>net5.0<span class="nt">&lt;/TargetFramework&gt;</span> + <span class="nt">&lt;LangVersion&gt;</span>preview<span class="nt">&lt;/LangVersion&gt;</span> + <span class="nt">&lt;/PropertyGroup&gt;</span> +<span class="nt">&lt;/Project&gt;</span> +</code></pre></div> + +<p>And you're ready to play with the awesome features available in the preview. Let's code a way to get the image of the day from NASA API and print the Picture of the Day. No awesome code here, it's really a way to show how simple a simple call could be. After here, why not save the image in a file? Maybe send the file over telegram?</p> +<div class="highlight"><pre><span></span><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Net.Http</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Text.Json</span><span class="p">;</span> + +<span class="kt">var</span> <span class="n">API</span> <span class="p">=</span> <span class="s">&quot;https://api.nasa.gov/planetary/apod?hd=true&amp;api_key=DEMO_KEY&quot;</span><span class="p">;</span> +<span class="kt">var</span> <span class="n">cli</span> <span class="p">=</span> <span class="k">new</span> <span class="n">HttpClient</span><span class="p">();</span> + +<span class="kt">var</span> <span class="n">response</span> <span class="p">=</span> <span class="k">await</span> <span class="n">cli</span><span class="p">.</span><span class="n">GetAsync</span><span class="p">(</span><span class="n">API</span><span class="p">);</span> +<span class="kt">var</span> <span class="n">data</span> <span class="p">=</span> <span class="n">JsonSerializer</span><span class="p">.</span><span class="n">Deserialize</span><span class="p">&lt;</span><span class="n">NasaApi</span><span class="p">&gt;(</span><span class="k">await</span> <span class="n">response</span><span class="p">.</span><span class="n">Content</span><span class="p">.</span><span class="n">ReadAsStringAsync</span><span class="p">());</span> + +<span class="n">Console</span><span class="p">.</span><span class="n">WriteLine</span><span class="p">(</span><span class="n">data</span><span class="p">.</span><span class="n">Url</span><span class="p">);</span> +</code></pre></div> + +<p>That's it for today folks. Keep an eye open for the awesome features C# 9 will bring to us, there's plenty more features already available.</p>Top Level Statement no C# 92020-07-29T19:00:00-03:002020-07-29T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-07-29:/pt/top_level_statement_csharp_9.html<p>Olá pessoal, venho hoje falar sobre uma novidade que estará disponível na versão 9 do C#. Toda vez que você deseja criar um novo projeto, você sempre tem o mesmo arquivo Main, com a mesma estrutura. Na próxima versão do C# (versão 9), nós teremos uma nova funcionalidade chamada <code>Top …</code></p><p>Olá pessoal, venho hoje falar sobre uma novidade que estará disponível na versão 9 do C#. Toda vez que você deseja criar um novo projeto, você sempre tem o mesmo arquivo Main, com a mesma estrutura. Na próxima versão do C# (versão 9), nós teremos uma nova funcionalidade chamada <code>Top Level Statement</code>. Com isto, poderemos programar a nossa aplicação sem toda aquela estrutura de <code>namespace/class/public void static main</code>. Veja o código abaixo.</p> +<div class="highlight"><pre><span></span><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span> + +<span class="n">Console</span><span class="p">.</span><span class="n">WriteLine</span><span class="p">(</span><span class="s">&quot;Hello World!&quot;</span><span class="p">);</span> +</code></pre></div> + +<p>Parece muito simples, não é? Com isto, você pode brincar com seu código e até mesmo programar uma pequena WEB API. Para começar a brincar com estas novas <em>features</em>, primeiramente faça o download do preview do <a href="https://dotnet.microsoft.com/download/dotnet/5.0">.net 5 SDK</a> e modifique o seu arquivo <code>.csproj</code> para apontar o framework para <code>.net5.0</code> e a versão de preview da linguagem. Abaixo como uma aplicação de console deve ficar.</p> +<div class="highlight"><pre><span></span><code><span class="nt">&lt;Project</span> <span class="na">Sdk=</span><span class="s">&quot;Microsoft.NET.Sdk&quot;</span><span class="nt">&gt;</span> + <span class="nt">&lt;PropertyGroup&gt;</span> + <span class="nt">&lt;OutputType&gt;</span>Exe<span class="nt">&lt;/OutputType&gt;</span> + <span class="nt">&lt;TargetFramework&gt;</span>net5.0<span class="nt">&lt;/TargetFramework&gt;</span> + <span class="nt">&lt;LangVersion&gt;</span>preview<span class="nt">&lt;/LangVersion&gt;</span> + <span class="nt">&lt;/PropertyGroup&gt;</span> +<span class="nt">&lt;/Project&gt;</span> +</code></pre></div> + +<p>E assim você está pronto para brincar com as novas funcionalidades que estão disponíveis na versão preview. Vamos programar uma aplicação simples que faz uma requisição na API da NASA e printe a Imagem do Dia no console. Não é nenhum código mirabolante, é simplesmente para exemplificar o quão simples uma simples chamada de API pode ser. Feito isto, porque não salvar a imagem como um arquivo? Ou então enviar essa imagem via telegram?</p> +<div class="highlight"><pre><span></span><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Net.Http</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Text.Json</span><span class="p">;</span> + +<span class="kt">var</span> <span class="n">API</span> <span class="p">=</span> <span class="s">&quot;https://api.nasa.gov/planetary/apod?hd=true&amp;api_key=DEMO_KEY&quot;</span><span class="p">;</span> +<span class="kt">var</span> <span class="n">cli</span> <span class="p">=</span> <span class="k">new</span> <span class="n">HttpClient</span><span class="p">();</span> + +<span class="kt">var</span> <span class="n">response</span> <span class="p">=</span> <span class="k">await</span> <span class="n">cli</span><span class="p">.</span><span class="n">GetAsync</span><span class="p">(</span><span class="n">API</span><span class="p">);</span> +<span class="kt">var</span> <span class="n">data</span> <span class="p">=</span> <span class="n">JsonSerializer</span><span class="p">.</span><span class="n">Deserialize</span><span class="p">&lt;</span><span class="n">NasaApi</span><span class="p">&gt;(</span><span class="k">await</span> <span class="n">response</span><span class="p">.</span><span class="n">Content</span><span class="p">.</span><span class="n">ReadAsStringAsync</span><span class="p">());</span> + +<span class="n">Console</span><span class="p">.</span><span class="n">WriteLine</span><span class="p">(</span><span class="n">data</span><span class="p">.</span><span class="n">Url</span><span class="p">);</span> +</code></pre></div> + +<p>Por hoje é isso. Fique de olho nas novas features que o C# 9 vai nos trazer. Já temos várias disponíveis hoje para testar, esta é apenas uma delas.</p>Zabbix poller processes more than 75%2020-07-02T19:00:00-03:002020-07-02T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-07-02:/zabbix-poller-processes-more-than-75.html<p>Hey folks, this is the third post about tweaking the Zabbix configurations. All changes that I've suggested here were based on a Zabbix Server with 50+ hosts. Another thing that can happen to your server, it's the poller get overwhelmed by the amount of servers that need to be polled …</p><p>Hey folks, this is the third post about tweaking the Zabbix configurations. All changes that I've suggested here were based on a Zabbix Server with 50+ hosts. Another thing that can happen to your server, it's the poller get overwhelmed by the amount of servers that need to be polled plus the ones that are not responding. Bellow two images where you can see the log and the graphic where you can see the usage percent. </p> +<p><img alt="Dashboard log about the poller processes" src="/images/zabbix_pooler.png"></p> +<p><img alt="Graph showing the utilization percent of each collector" src="/images/zabbix_pooler_3.png"></p> +<p>To solve, let's go back to the <code>zabbix_server.conf</code> file and find two variables, <code>StartPollers</code> and <code>StartPollersUnreachable</code>. Increase them as needed. There's no magic number, you must see what works for you. But keep in mind that the <code>StartPollersUnreachable</code> is responsible for that host that can't be "reached" (of course) and will hold your poller more time.</p> +<div class="highlight"><pre><span></span><code><span class="c1">### Option: StartPollers</span> +<span class="c1"># Number of pre-forked instances of pollers.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 0-1000</span> +<span class="c1"># Default:</span> +<span class="na">StartPollers</span><span class="o">=</span><span class="s">20</span> + +<span class="c1">#...</span> + +<span class="c1">### Option: StartPollersUnreachable</span> +<span class="c1"># Number of pre-forked instances of pollers for unreachable hosts (including IPMI and Java).</span> +<span class="c1"># At least one poller for unreachable hosts must be running if regular, IPMI or Java pollers</span> +<span class="c1"># are started.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 0-1000</span> +<span class="c1"># Default:</span> +<span class="na">StartPollersUnreachable</span><span class="o">=</span><span class="s">5</span> +</code></pre></div> + +<p>After the change, restart the server and wait a few moments and take a look again at your dashboard. Bellow the effect that I've got.</p> +<p><img alt="Graph showing the new utilization percent of the processes after the changes" src="/images/zabbix_pooler_4.png"></p>Zabbix poller processes more than 75%2020-07-02T19:00:00-03:002020-07-02T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-07-02:/pt/zabbix-poller-processes-more-than-75.html<p>Este é o terceiro post sobre configurações para o Zabbix. Todas as alterações que eu sugiro nestes posts, são baseadas em um servidor com 50+ hosts. Outro problema que pode ocorrer em seu servidor, é o poller de informações ficar sobrecarregado pela quantidade de servidores que ele precisa pegar carga …</p><p>Este é o terceiro post sobre configurações para o Zabbix. Todas as alterações que eu sugiro nestes posts, são baseadas em um servidor com 50+ hosts. Outro problema que pode ocorrer em seu servidor, é o poller de informações ficar sobrecarregado pela quantidade de servidores que ele precisa pegar carga de informações juntamente com os servidores que não respondem a requisição. Abaixo duas imagens onde você pode ver o log e um gráfico onde aparecem os percentuais de uso dos poller. </p> +<p><img alt="Dashboard log sobre o processo do poller" src="/images/zabbix_pooler.png"></p> +<p><img alt="Gráfico mostrando o percentual de utilização de cada coletor" src="/images/zabbix_pooler_3.png"></p> +<p>Para resolver o problema acima, vamos voltar ao arquivo de configuração <code>zabbix_server.conf</code> e localizar duas variáveis, <code>StartPollers</code> e <code>StartPollersUnreachable</code>. Aumente o valor delas conforme necessário. Não existe um número mágico, você deve verificar o que melhor funciona para você. Mas tenha em mente que <code>StartPollersUnreachable</code> é responsável por aqueles hosts que não respondem ou não são localizados e irão segurar a thread do poller por mais tempo, causando uma fila e um maior processamento/tempo de atualização.</p> +<div class="highlight"><pre><span></span><code><span class="c1">### Option: StartPollers</span> +<span class="c1"># Number of pre-forked instances of pollers.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 0-1000</span> +<span class="c1"># Default:</span> +<span class="na">StartPollers</span><span class="o">=</span><span class="s">20</span> + +<span class="c1">#...</span> + +<span class="c1">### Option: StartPollersUnreachable</span> +<span class="c1"># Number of pre-forked instances of pollers for unreachable hosts (including IPMI and Java).</span> +<span class="c1"># At least one poller for unreachable hosts must be running if regular, IPMI or Java pollers</span> +<span class="c1"># are started.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 0-1000</span> +<span class="c1"># Default:</span> +<span class="na">StartPollersUnreachable</span><span class="o">=</span><span class="s">5</span> +</code></pre></div> + +<p>Depois da alteração, reinicie o serviço e espere alguns momentos e veja o seu dashboard novamente. Abaixo o efeito que a troca teve em um dos servidores que acompanho.</p> +<p><img alt="Gráfico mostrando os novos percentuais de utilização dos processos após as alterações" src="/images/zabbix_pooler_4.png"></p>Monitoring a Website heath with Azure Functions2020-06-22T19:00:00-03:002020-06-22T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-06-22:/monitoring-website-heath-with-azure-functions.html<p>Sometimes you get your self in need to monitor a website's health or it's content for changes. Of course, there's plenty of options out there, but for the sake of curiosity, let's code our own to see what we can do. First things first. Everything you'll see here, you can …</p><p>Sometimes you get your self in need to monitor a website's health or it's content for changes. Of course, there's plenty of options out there, but for the sake of curiosity, let's code our own to see what we can do. First things first. Everything you'll see here, you can achieve with the <a href="https://azure.microsoft.com/free/">free tier</a> of azure.</p> +<p>The main idea of our app will be to monitor website health (status code). To create a new Azure Function Project, follow the steps below.</p> +<p><img alt="Steps to create a azure function project" src="/images/azure_functions.gif"></p> +<p>After creating the project, you'll have a few files. Open your main file and start coding. The main file will have a function called <code>Run</code> and you can code your request method. I've created an <code>async</code> method to make the request and log the output at the console. The full code you can see below.</p> +<div class="highlight"><pre><span></span><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Linq</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Net.Http</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Threading.Tasks</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">Microsoft.Azure.WebJobs</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">Microsoft.Azure.WebJobs.Host</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">Microsoft.Extensions.Logging</span><span class="p">;</span> + +<span class="k">namespace</span> <span class="nn">Sipmann.CheckMySite</span> +<span class="p">{</span> + <span class="k">public</span> <span class="k">static</span> <span class="k">class</span> <span class="nc">HttpCheck</span> + <span class="p">{</span> + + <span class="k">private</span> <span class="k">static</span> <span class="k">async</span> <span class="n">Task</span> <span class="nf">GetTask</span><span class="p">(</span><span class="kt">string</span> <span class="n">url</span><span class="p">,</span> <span class="n">ILogger</span> <span class="n">log</span><span class="p">)</span> + <span class="p">{</span> + <span class="kt">var</span> <span class="n">request</span> <span class="p">=</span> <span class="k">new</span> <span class="n">HttpRequestMessage</span><span class="p">(</span><span class="n">HttpMethod</span><span class="p">.</span><span class="n">Get</span><span class="p">,</span> <span class="n">url</span><span class="p">);</span> + + <span class="kt">var</span> <span class="n">client</span> <span class="p">=</span> <span class="k">new</span> <span class="n">HttpClient</span><span class="p">();</span> + <span class="kt">var</span> <span class="n">response</span> <span class="p">=</span> <span class="k">await</span> <span class="n">client</span><span class="p">.</span><span class="n">SendAsync</span><span class="p">(</span><span class="n">request</span><span class="p">);</span> + + <span class="k">if</span> <span class="p">(</span><span class="n">response</span><span class="p">.</span><span class="n">IsSuccessStatusCode</span><span class="p">)</span> + <span class="p">{</span> + <span class="n">log</span><span class="p">.</span><span class="n">LogInformation</span><span class="p">(</span><span class="err">$</span><span class="s">&quot;URL ${url} esta OK&quot;</span><span class="p">);</span> + <span class="p">}</span> + <span class="k">else</span> + <span class="p">{</span> + <span class="n">log</span><span class="p">.</span><span class="n">LogInformation</span><span class="p">(</span><span class="err">$</span><span class="s">&quot;URL ${url} não esta OK&quot;</span><span class="p">);</span> + <span class="p">}</span> + <span class="p">}</span> + +<span class="na"> [FunctionName(&quot;HttpCheck&quot;)]</span> + <span class="k">public</span> <span class="k">static</span> <span class="k">void</span> <span class="nf">Run</span><span class="p">([</span><span class="n">TimerTrigger</span><span class="p">(</span><span class="s">&quot;0 */5 * * * *&quot;</span><span class="p">)]</span><span class="n">TimerInfo</span> <span class="n">myTimer</span><span class="p">,</span> <span class="n">ILogger</span> <span class="n">log</span><span class="p">)</span> + <span class="p">{</span> + <span class="kt">var</span> <span class="n">urls</span> <span class="p">=</span> <span class="k">new</span><span class="p">[]{</span><span class="s">&quot;https://www.sipmann.com&quot;</span><span class="p">,</span> <span class="s">&quot;https://www.canezecanez.com.br&quot;</span><span class="p">};</span> + + <span class="c1">// Start every request and wait for them all to complete</span> + <span class="n">Task</span><span class="p">.</span><span class="n">WaitAll</span><span class="p">(</span><span class="n">urls</span><span class="p">.</span><span class="n">Select</span><span class="p">(</span><span class="n">url</span> <span class="p">=&gt;</span> <span class="n">GetTask</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">log</span><span class="p">)).</span><span class="n">ToArray</span><span class="p">());</span> + <span class="n">log</span><span class="p">.</span><span class="n">LogInformation</span><span class="p">(</span><span class="err">$</span><span class="s">&quot;Finalizou a fila&quot;</span><span class="p">);</span> + <span class="p">}</span> + <span class="p">}</span> +<span class="p">}</span> +</code></pre></div> + +<p>Now you can enhance the function and maybe send some alerts like a Telegram message when one of your sites went down.</p>Monitorando a disponibilidade de um Website com Azure Functions2020-06-22T19:00:00-03:002020-06-22T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-06-22:/pt/monitoring-website-heath-with-azure-functions.html<p>Algumas vezes você se depara com a necessidade de monitorar a disponibilidade de um website ou mudanças em seu conteúdo. É claro que temos diversas opções disponíveis no mercado, mas para fins de curiosidade, vamos programar o nosso próprio e ver o que podemos fazer. Primeiramente, tudo que você ver …</p><p>Algumas vezes você se depara com a necessidade de monitorar a disponibilidade de um website ou mudanças em seu conteúdo. É claro que temos diversas opções disponíveis no mercado, mas para fins de curiosidade, vamos programar o nosso próprio e ver o que podemos fazer. Primeiramente, tudo que você ver aqui, você pode utilizar o <a href="https://azure.microsoft.com/free/">tier gratuito</a> da Azure.</p> +<p>A ideia principal da nossa aplicação vai ser monitorar a disponibilidade do website (status code). Para criar um projeto de Azure Function, siga os passos abaixo.</p> +<p><img alt="Passos para criar um projeto Azure Functions" src="/images/azure_functions.gif"></p> +<p>Depois de criar o projeto, você vai ter alguns arquivos. Abra o arquivo principal (<code>HttpCheck.cs</code> no meu caso) e começe a programar. O arquivo principal terá uma função chamada <code>Run</code> e você pode progamar nela o seu request. Eu criei um método <code>async</code> para fazer as requisições e printar a saída diretamente no console. O código completo pode ser visto abaixo.</p> +<div class="highlight"><pre><span></span><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Linq</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Net.Http</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Threading.Tasks</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">Microsoft.Azure.WebJobs</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">Microsoft.Azure.WebJobs.Host</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">Microsoft.Extensions.Logging</span><span class="p">;</span> + +<span class="k">namespace</span> <span class="nn">Sipmann.CheckMySite</span> +<span class="p">{</span> + <span class="k">public</span> <span class="k">static</span> <span class="k">class</span> <span class="nc">HttpCheck</span> + <span class="p">{</span> + + <span class="k">private</span> <span class="k">static</span> <span class="k">async</span> <span class="n">Task</span> <span class="nf">GetTask</span><span class="p">(</span><span class="kt">string</span> <span class="n">url</span><span class="p">,</span> <span class="n">ILogger</span> <span class="n">log</span><span class="p">)</span> + <span class="p">{</span> + <span class="kt">var</span> <span class="n">request</span> <span class="p">=</span> <span class="k">new</span> <span class="n">HttpRequestMessage</span><span class="p">(</span><span class="n">HttpMethod</span><span class="p">.</span><span class="n">Get</span><span class="p">,</span> <span class="n">url</span><span class="p">);</span> + + <span class="kt">var</span> <span class="n">client</span> <span class="p">=</span> <span class="k">new</span> <span class="n">HttpClient</span><span class="p">();</span> + <span class="kt">var</span> <span class="n">response</span> <span class="p">=</span> <span class="k">await</span> <span class="n">client</span><span class="p">.</span><span class="n">SendAsync</span><span class="p">(</span><span class="n">request</span><span class="p">);</span> + + <span class="k">if</span> <span class="p">(</span><span class="n">response</span><span class="p">.</span><span class="n">IsSuccessStatusCode</span><span class="p">)</span> + <span class="p">{</span> + <span class="n">log</span><span class="p">.</span><span class="n">LogInformation</span><span class="p">(</span><span class="err">$</span><span class="s">&quot;URL ${url} esta OK&quot;</span><span class="p">);</span> + <span class="p">}</span> + <span class="k">else</span> + <span class="p">{</span> + <span class="n">log</span><span class="p">.</span><span class="n">LogInformation</span><span class="p">(</span><span class="err">$</span><span class="s">&quot;URL ${url} não esta OK&quot;</span><span class="p">);</span> + <span class="p">}</span> + <span class="p">}</span> + +<span class="na"> [FunctionName(&quot;HttpCheck&quot;)]</span> + <span class="k">public</span> <span class="k">static</span> <span class="k">void</span> <span class="nf">Run</span><span class="p">([</span><span class="n">TimerTrigger</span><span class="p">(</span><span class="s">&quot;0 */5 * * * *&quot;</span><span class="p">)]</span><span class="n">TimerInfo</span> <span class="n">myTimer</span><span class="p">,</span> <span class="n">ILogger</span> <span class="n">log</span><span class="p">)</span> + <span class="p">{</span> + <span class="c1">// URL a verificar a saúde</span> + <span class="kt">var</span> <span class="n">urls</span> <span class="p">=</span> <span class="k">new</span><span class="p">[]{</span><span class="s">&quot;https://www.sipmann.com&quot;</span><span class="p">,</span> <span class="s">&quot;https://www.canezecanez.com.br&quot;</span><span class="p">};</span> + + <span class="c1">// Starta cada request e aguarda todos de uma vez só</span> + <span class="n">Task</span><span class="p">.</span><span class="n">WaitAll</span><span class="p">(</span><span class="n">urls</span><span class="p">.</span><span class="n">Select</span><span class="p">(</span><span class="n">url</span> <span class="p">=&gt;</span> <span class="n">GetTask</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">log</span><span class="p">)).</span><span class="n">ToArray</span><span class="p">());</span> + <span class="n">log</span><span class="p">.</span><span class="n">LogInformation</span><span class="p">(</span><span class="err">$</span><span class="s">&quot;Finalizou a fila&quot;</span><span class="p">);</span> + <span class="p">}</span> + <span class="p">}</span> +<span class="p">}</span> +</code></pre></div> + +<p>Agora você pode melhorar a função e talvez enviar alguns alertas. Como por exêmplo mensagens no Telegram quando um dos sites ficar off (status code 404).</p>Azure Data Fundamentals certification with 80% discount2020-06-09T12:30:00-03:002020-06-09T12:30:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-06-09:/azure-data-fundamentals-certification-80-discount.html<p>Hey folks, if you want to achieve some certification this year, keep an eye open for vouchers. A few months ago, Oracle released a set of free courses with certifications. Now it's Microsoft time. Microsoft is updating they're certifications and we have a voucher of 80% discount using the coupon …</p><p>Hey folks, if you want to achieve some certification this year, keep an eye open for vouchers. A few months ago, Oracle released a set of free courses with certifications. Now it's Microsoft time. Microsoft is updating they're certifications and we have a voucher of 80% discount using the coupon <strong>DP900Norfolk</strong> at the checkout of the beta certification DP-900. </p> +<p>Be aware that this certification is in beta and the result won't be instantly available as the regular ones. Access the following link and schedule your exam. <a href="https://docs.microsoft.com/pt-br/learn/certifications/exams/dp-900" target="_blank">https://docs.microsoft.com/pt-br/learn/certifications/exams/dp-900</a>.</p> +<p><strong>Update:</strong> There is a 80% voucher also for <a href="https://docs.microsoft.com/en-us/learn/certifications/azure-ai-fundamentals" target="_blank">https://docs.microsoft.com/en-us/learn/certifications/azure-ai-fundamentals</a>. Voucher: <strong>AI900Saratoga</strong></p>Zabbix ICMP pinger processes more than 75%2020-05-25T16:00:00-03:002020-05-25T16:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-05-25:/zabbix-icmp-pinger-processes-more-than-75.html<p>So your monitoring sytems have grown and your zabbix started loggin "Zabbix icmp pinger processes more than 75% busy" at the dashboard.</p> +<p><img alt="Dashboard do zabbix avisando sobre o erro" src="/images/zabbix_pinger01.png"></p> +<p>All you have to do is open your config file (<code>/etc/zabbix/zabbix_server.conf</code>) and find the a tag named <code>StartPingers</code>. It'll be commented by default. Uncomment it …</p><p>So your monitoring sytems have grown and your zabbix started loggin "Zabbix icmp pinger processes more than 75% busy" at the dashboard.</p> +<p><img alt="Dashboard do zabbix avisando sobre o erro" src="/images/zabbix_pinger01.png"></p> +<p>All you have to do is open your config file (<code>/etc/zabbix/zabbix_server.conf</code>) and find the a tag named <code>StartPingers</code>. It'll be commented by default. Uncomment it and set it's value to something like 3 or 4. It should solve your problem.</p> +<div class="highlight"><pre><span></span><code><span class="c1">### Option: StartPingers</span> +<span class="c1"># Number of pre-forked instances of ICMP pingers.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 0-1000</span> +<span class="c1"># Default:</span> +<span class="nv">StartPingers</span><span class="o">=</span><span class="m">4</span> +</code></pre></div> + +<h2>How many Pingers do I need?</h2> +<p>Well, there is no exact answer to this. If you set it too high, you'll be wasting resources. The best way to solve, it's increasing them as soon as you notice the percentage growing.</p>Zabbix ICMP pinger processes more than 75%2020-05-25T16:00:00-03:002020-05-25T16:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-05-25:/pt/zabbix-icmp-pinger-processes-more-than-75.html<p>Então o seu systema de monitoramento creasceu e o seu Zabbix começou a printar "<em>Zabbix icmp pinger processes more than 75% busy</em>" no seu dashboard.</p> +<p><img alt="Dashboard do zabbix avisando sobre o erro" src="/images/zabbix_pinger01.png"></p> +<p>Tudo que você tem a fazer é abrir o seu arquivo de configuração (<code>/etc/zabbix/zabbix_server.conf</code>) e localizar a tag chamada <code>StartPingers</code>. Ela deve …</p><p>Então o seu systema de monitoramento creasceu e o seu Zabbix começou a printar "<em>Zabbix icmp pinger processes more than 75% busy</em>" no seu dashboard.</p> +<p><img alt="Dashboard do zabbix avisando sobre o erro" src="/images/zabbix_pinger01.png"></p> +<p>Tudo que você tem a fazer é abrir o seu arquivo de configuração (<code>/etc/zabbix/zabbix_server.conf</code>) e localizar a tag chamada <code>StartPingers</code>. Ela deve estar comentáda por padrão. Descomente a lina e define o seu valor para algo como 3 or 4. Deve resolver seu problema, ao menos até um próximo crescimento do seu monitoramento.</p> +<div class="highlight"><pre><span></span><code><span class="c1">### Option: StartPingers</span> +<span class="c1"># Number of pre-forked instances of ICMP pingers.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 0-1000</span> +<span class="c1"># Default:</span> +<span class="nv">StartPingers</span><span class="o">=</span><span class="m">4</span> +</code></pre></div>Zabbix Server Out of Memory2020-02-27T19:00:00-03:002020-02-27T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-02-27:/zabbix-server-out-of-memory-crash.html<p>Do you have a crashing Zabbix Server and looking through the log <code>/var/log/zabbix/zabbix_server.log</code> you see the following out of memory message?</p> +<div class="highlight"><pre><span></span><code>__mem_malloc: skipped <span class="m">0</span> asked <span class="m">24</span> skip_min <span class="m">18446744073709551615</span> skip_max <span class="m">0</span> +<span class="o">[</span>file:dbconfig.c,line:94<span class="o">]</span> __zbx_mem_realloc<span class="o">()</span>: out of memory <span class="o">(</span>requested <span class="m">16</span> bytes<span class="o">)</span> +<span class="o">[</span>file:dbconfig.c,line …</code></pre></div><p>Do you have a crashing Zabbix Server and looking through the log <code>/var/log/zabbix/zabbix_server.log</code> you see the following out of memory message?</p> +<div class="highlight"><pre><span></span><code>__mem_malloc: skipped <span class="m">0</span> asked <span class="m">24</span> skip_min <span class="m">18446744073709551615</span> skip_max <span class="m">0</span> +<span class="o">[</span>file:dbconfig.c,line:94<span class="o">]</span> __zbx_mem_realloc<span class="o">()</span>: out of memory <span class="o">(</span>requested <span class="m">16</span> bytes<span class="o">)</span> +<span class="o">[</span>file:dbconfig.c,line:94<span class="o">]</span> __zbx_mem_realloc<span class="o">()</span>: please increase CacheSize configuration parameter +</code></pre></div> + +<p>Besides the clear solution to the error, that's a common issue on servers that have a few monitoring items on it (servers, switches, firewalls, databases, etc...). To solve, go to your zabbix_server.conf and look for the CacheSize property and set it to a higher value. Its default should be 8M. At a customer that has somewhere between 4 servers, 7 firewalls/appliances, and a few other things, a 32M did the job, but you can set up to 8G.</p> +<p>See ya folks.</p>Zabbix Server Out of Memory2020-02-27T19:00:00-03:002020-02-27T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-02-27:/pt/zabbix-server-out-of-memory-crash.html<p>Você tem um servidor Zabbix crashando e observando o arquivo de log <code>/var/log/zabbix/zabbix_server.log</code> você localiza a seguinte mensagem referênciando falta de memória?</p> +<div class="highlight"><pre><span></span><code>__mem_malloc: skipped <span class="m">0</span> asked <span class="m">24</span> skip_min <span class="m">18446744073709551615</span> skip_max <span class="m">0</span> +<span class="o">[</span>file:dbconfig.c,line:94<span class="o">]</span> __zbx_mem_realloc<span class="o">()</span>: out of memory <span class="o">(</span>requested <span class="m">16</span> bytes<span class="o">)</span> +<span class="o">[</span>file:dbconfig.c …</code></pre></div><p>Você tem um servidor Zabbix crashando e observando o arquivo de log <code>/var/log/zabbix/zabbix_server.log</code> você localiza a seguinte mensagem referênciando falta de memória?</p> +<div class="highlight"><pre><span></span><code>__mem_malloc: skipped <span class="m">0</span> asked <span class="m">24</span> skip_min <span class="m">18446744073709551615</span> skip_max <span class="m">0</span> +<span class="o">[</span>file:dbconfig.c,line:94<span class="o">]</span> __zbx_mem_realloc<span class="o">()</span>: out of memory <span class="o">(</span>requested <span class="m">16</span> bytes<span class="o">)</span> +<span class="o">[</span>file:dbconfig.c,line:94<span class="o">]</span> __zbx_mem_realloc<span class="o">()</span>: please increase CacheSize configuration parameter +</code></pre></div> + +<p>Apesar da simples solução para o erro, isso acaba sendo um problema comum em servidores que tem uma certa quantidade de itens sendo monitorados (servidores, switches, firewalls, bancos, etc...). Para resolver o problema, vá até o ser arquivo <code>zabbix_server.conf</code> e procure pela propriedade <code>CacheSize</code> e sete o seu valor para uma quantidade maior. O seu valor default deve ser algo como 8M. Em clientes que tenham algo como 4 servidores, 7 firewalls/appliances, e algumas outras coisas (bancos, apps), 32M deve resolver o problema, mas você pode setar até algo como 8G (ressalto que mais memória nem sempre é melhor).</p> +<p>Até breve.</p>Flutter + firebase auth crashing2019-10-03T19:00:00-03:002019-10-03T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2019-10-03:/flutter_with_firebase_auth_crashing.html<p>Hey Folks, recently I've started learning <a href="https://flutter.dev/">Flutter</a> and right after a TODO List, I tried a Firebase integration. But as soon as I started setting the dependencies, my app stopped opening... just a crash. After a few logs digging, I've found the following log.</p> +<div class="highlight"><pre><span></span><code>AndroidRuntime: FATAL EXCEPTION: main +AndroidRuntime: Process …</code></pre></div><p>Hey Folks, recently I've started learning <a href="https://flutter.dev/">Flutter</a> and right after a TODO List, I tried a Firebase integration. But as soon as I started setting the dependencies, my app stopped opening... just a crash. After a few logs digging, I've found the following log.</p> +<div class="highlight"><pre><span></span><code>AndroidRuntime: FATAL EXCEPTION: main +AndroidRuntime: Process: com.example.diadocasal, PID: <span class="m">13672</span> +AndroidRuntime: java.lang.NoClassDefFoundError: Failed resolution of: Landroid/support/v4/util/ArrayMap<span class="p">;</span> +AndroidRuntime: at com.google.android.gms.internal.measurement.zzca.&lt;clinit&gt;<span class="o">(</span>Unknown Source:60<span class="o">)</span> +AndroidRuntime: at com.google.android.gms.internal.measurement.zzcm.zzr<span class="o">(</span>Unknown Source:7<span class="o">)</span> +AndroidRuntime: at com.google.android.gms.measurement.internal.zzfj.&lt;init&gt;<span class="o">(</span>Unknown Source:23<span class="o">)</span> +</code></pre></div> + +<p>Notice the "NoClassDefFound" of an ArrayMap. To solve that I did the following changes to the files:</p> +<div class="highlight"><pre><span></span><code><span class="c1">//build.gradle file</span> + <span class="n">ext</span><span class="p">.</span><span class="na">kotlin_version</span> <span class="o">=</span> <span class="err">&#39;</span><span class="mf">1.3.20</span><span class="err">&#39;</span> +<span class="o">[</span><span class="p">...</span><span class="o">]</span> + <span class="n">dependencies</span> <span class="p">{</span> + <span class="n">classpath</span> <span class="err">&#39;</span><span class="n">com</span><span class="p">.</span><span class="na">android</span><span class="p">.</span><span class="na">tools</span><span class="p">.</span><span class="na">build</span><span class="p">:</span><span class="n">gradle</span><span class="p">:</span><span class="mf">3.3.0</span><span class="err">&#39;</span> <span class="c1">// gradle version</span> +</code></pre></div> + +<div class="highlight"><pre><span></span><code><span class="c1">;gradle.properties file</span> +<span class="na">org.gradle.jvmargs</span><span class="o">=</span><span class="s">-Xmx1536M ;mine have just this line at first</span> +<span class="na">android.useAndroidX</span><span class="o">=</span><span class="s">true ; uses androidX instead of the default support library</span> +<span class="na">android.enableJetifier</span><span class="o">=</span><span class="s">true ; uses jetpack libraries</span> +<span class="na">android.enableR8</span><span class="o">=</span><span class="s">true ; the new code shriker</span> +</code></pre></div> + +<p>After that, voilà, app up and running.</p>Removing a user from SQL Server database who owns a schema2019-09-06T07:00:00-03:002020-10-21T18:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2019-09-06:/removing-user-from-sql-server-database.html<p>Your customer urge you to drop a user from the MsSQL Server database, but you stuck with the following related error:</p> +<div class="highlight"><pre><span></span><code><span class="n">Error</span><span class="o">:</span> <span class="mi">15138</span> <span class="n">The</span> <span class="n">database</span> <span class="n">principal</span> <span class="n">owns</span> <span class="n">a</span> <span class="n">schema</span> <span class="k">in</span> <span class="n">the</span> <span class="n">database</span><span class="o">,</span> <span class="n">and</span> <span class="n">cannot</span> <span class="n">be</span> <span class="n">dropped</span><span class="o">.</span> +</code></pre></div> + +<p>That means that the user owns one or more shcemas of your database. If …</p><p>Your customer urge you to drop a user from the MsSQL Server database, but you stuck with the following related error:</p> +<div class="highlight"><pre><span></span><code><span class="n">Error</span><span class="o">:</span> <span class="mi">15138</span> <span class="n">The</span> <span class="n">database</span> <span class="n">principal</span> <span class="n">owns</span> <span class="n">a</span> <span class="n">schema</span> <span class="k">in</span> <span class="n">the</span> <span class="n">database</span><span class="o">,</span> <span class="n">and</span> <span class="n">cannot</span> <span class="n">be</span> <span class="n">dropped</span><span class="o">.</span> +</code></pre></div> + +<p>That means that the user owns one or more shcemas of your database. If you don't have access to the SSMS to see which schema or objects the user owns, the following SQL should do the job.</p> +<div class="highlight"><pre><span></span><code><span class="k">USE</span><span class="w"> </span><span class="o">[</span><span class="n">DATABASENAME</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> + +<span class="k">select</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Objeto</span><span class="p">,</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Owner</span><span class="w"></span> +<span class="k">from</span><span class="w"> </span><span class="n">sys</span><span class="p">.</span><span class="n">schemas</span><span class="w"> </span><span class="n">so</span><span class="w"></span> +<span class="k">inner</span><span class="w"> </span><span class="k">join</span><span class="w"> </span><span class="n">sysusers</span><span class="w"> </span><span class="n">su</span><span class="w"> </span><span class="k">on</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">principal_id</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">uid</span><span class="w"></span> +<span class="k">where</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">&#39;username&#39;</span><span class="w"></span> + +<span class="k">select</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Objeto</span><span class="p">,</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Owner</span><span class="p">,</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">xtype</span><span class="w"> </span><span class="n">Tipo</span><span class="w"></span> +<span class="k">from</span><span class="w"> </span><span class="n">sys</span><span class="p">.</span><span class="n">sysobjects</span><span class="w"> </span><span class="n">so</span><span class="w"></span> +<span class="k">inner</span><span class="w"> </span><span class="k">join</span><span class="w"> </span><span class="n">sysusers</span><span class="w"> </span><span class="n">su</span><span class="w"> </span><span class="k">on</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">uid</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">uid</span><span class="w"></span> +<span class="k">where</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">&#39;username&#39;</span><span class="w"></span> +</code></pre></div> + +<p>Once you have the objects/schemas owned by the user, you can change them with the following SQL (schema change sample):</p> +<div class="highlight"><pre><span></span><code><span class="k">USE</span><span class="w"> </span><span class="o">[</span><span class="n">DATABASENAME</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +<span class="k">ALTER</span><span class="w"> </span><span class="k">AUTHORIZATION</span><span class="w"> </span><span class="k">ON</span><span class="w"> </span><span class="k">SCHEMA</span><span class="o">::[</span><span class="n">db_datareader</span><span class="o">]</span><span class="w"> </span><span class="k">TO</span><span class="w"> </span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="w"> </span><span class="c1">-- new owner username</span> +<span class="k">ALTER</span><span class="w"> </span><span class="k">AUTHORIZATION</span><span class="w"> </span><span class="k">ON</span><span class="w"> </span><span class="k">SCHEMA</span><span class="o">::[</span><span class="n">db_datawriter</span><span class="o">]</span><span class="w"> </span><span class="k">TO</span><span class="w"> </span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +</code></pre></div> + +<p>Then you're ready to drop the user <code>DROP USER [username]</code></p> +<h2>How to list all the schemas and it's owners?</h2> +<p>Here's a script to list schemas and it's owners.</p> +<div class="highlight"><pre><span></span><code><span class="k">USE</span><span class="w"> </span><span class="o">[</span><span class="n">DATABASENAME</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +<span class="k">SELECT</span><span class="w"></span> +<span class="w"> </span><span class="nf">schema_name</span><span class="p">(</span><span class="nf">schema_id</span><span class="p">)</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="n">schemaname</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="nf">user_name</span><span class="p">(</span><span class="n">schm</span><span class="p">.</span><span class="n">principal_id</span><span class="p">)</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="n">username</span><span class="p">,</span><span class="w"> </span><span class="o">*</span><span class="w"></span> +<span class="k">FROM</span><span class="w"> </span><span class="n">sys</span><span class="p">.</span><span class="n">schemas</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="n">schm</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +</code></pre></div>Removendo um usuário de uma base SQL Server2019-09-06T07:00:00-03:002020-10-21T18:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2019-09-06:/pt/removing-user-from-sql-server-database.html<p>O seu cliente lhe pede com urgência para <em>dropar</em> um usuário da sua base MsSQL Server, mas você trava com o seguinte aviso de erro:</p> +<div class="highlight"><pre><span></span><code><span class="n">Error</span><span class="o">:</span> <span class="mi">15138</span> <span class="n">The</span> <span class="n">database</span> <span class="n">principal</span> <span class="n">owns</span> <span class="n">a</span> <span class="n">schema</span> <span class="k">in</span> <span class="n">the</span> <span class="n">database</span><span class="o">,</span> <span class="n">and</span> <span class="n">cannot</span> <span class="n">be</span> <span class="n">dropped</span><span class="o">.</span> +</code></pre></div> + +<p>Se você não possui (ou no momento não consegue acesso …</p><p>O seu cliente lhe pede com urgência para <em>dropar</em> um usuário da sua base MsSQL Server, mas você trava com o seguinte aviso de erro:</p> +<div class="highlight"><pre><span></span><code><span class="n">Error</span><span class="o">:</span> <span class="mi">15138</span> <span class="n">The</span> <span class="n">database</span> <span class="n">principal</span> <span class="n">owns</span> <span class="n">a</span> <span class="n">schema</span> <span class="k">in</span> <span class="n">the</span> <span class="n">database</span><span class="o">,</span> <span class="n">and</span> <span class="n">cannot</span> <span class="n">be</span> <span class="n">dropped</span><span class="o">.</span> +</code></pre></div> + +<p>Se você não possui (ou no momento não consegue acesso) ao SSMS (SQL Server Management Studio) para verificar quais schemas ou objetos o usuário é "dono", a seguinte SQL vai resolver o problema.</p> +<div class="highlight"><pre><span></span><code><span class="k">USE</span><span class="w"> </span><span class="o">[</span><span class="n">DATABASENAME</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> + +<span class="k">select</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Objeto</span><span class="p">,</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Owner</span><span class="w"></span> +<span class="k">from</span><span class="w"> </span><span class="n">sys</span><span class="p">.</span><span class="n">schemas</span><span class="w"> </span><span class="n">so</span><span class="w"></span> +<span class="k">inner</span><span class="w"> </span><span class="k">join</span><span class="w"> </span><span class="n">sysusers</span><span class="w"> </span><span class="n">su</span><span class="w"> </span><span class="k">on</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">principal_id</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">uid</span><span class="w"></span> +<span class="k">where</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">&#39;username&#39;</span><span class="w"></span> + +<span class="k">select</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Objeto</span><span class="p">,</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Owner</span><span class="p">,</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">xtype</span><span class="w"> </span><span class="n">Tipo</span><span class="w"></span> +<span class="k">from</span><span class="w"> </span><span class="n">sys</span><span class="p">.</span><span class="n">sysobjects</span><span class="w"> </span><span class="n">so</span><span class="w"></span> +<span class="k">inner</span><span class="w"> </span><span class="k">join</span><span class="w"> </span><span class="n">sysusers</span><span class="w"> </span><span class="n">su</span><span class="w"> </span><span class="k">on</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">uid</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">uid</span><span class="w"></span> +<span class="k">where</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">&#39;username&#39;</span><span class="w"></span> +</code></pre></div> + +<p>Assim que você tiver os objetos/schemas que o usuário é dono, você pode alterar os mesmos com a seguinte SQL (exemplo de troca de schema):</p> +<div class="highlight"><pre><span></span><code><span class="k">USE</span><span class="w"> </span><span class="o">[</span><span class="n">DATABASENAME</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +<span class="k">ALTER</span><span class="w"> </span><span class="k">AUTHORIZATION</span><span class="w"> </span><span class="k">ON</span><span class="w"> </span><span class="k">SCHEMA</span><span class="o">::[</span><span class="n">db_datareader</span><span class="o">]</span><span class="w"> </span><span class="k">TO</span><span class="w"> </span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="w"> </span><span class="c1">-- username do novo dono</span> +<span class="k">ALTER</span><span class="w"> </span><span class="k">AUTHORIZATION</span><span class="w"> </span><span class="k">ON</span><span class="w"> </span><span class="k">SCHEMA</span><span class="o">::[</span><span class="n">db_datawriter</span><span class="o">]</span><span class="w"> </span><span class="k">TO</span><span class="w"> </span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +</code></pre></div> + +<p>Então, você pode dropar o usuário <code>DROP USER [username]</code>.</p>Limiting Connection Resources on SQL Server2019-08-12T12:00:00-03:002019-08-12T12:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2019-08-12:/limiting-connection-resources-sql-server.html<p>Have you ever suffered from a slow SQLServer database? Someone love to run that heavy query in the database? Resource Governor to the rescue. You can set a few rules on how users (connections actually) will use the server/database resources based on a few things.</p> +<p>First things first, if …</p><p>Have you ever suffered from a slow SQLServer database? Someone love to run that heavy query in the database? Resource Governor to the rescue. You can set a few rules on how users (connections actually) will use the server/database resources based on a few things.</p> +<p>First things first, if you don't have DAC enabled, enable it now. Dealing with resource governor can lock you out of the database and leave you without action (almost... you can start the server with -c -m -f).</p> +<p>Now to understand how Resource Governor works, we have a few keywords <code>resource pool</code>, <code>workload group</code> e <code>Classifier Function</code>.</p> +<p><img alt="Pool Sample" src="/images/sql-pool.png"></p> +<h2>Resource Pool</h2> +<p>First, we have the Resource Pool, with is the bigger resource group that we have the ability to manage. With it, we can set a few things like: <code>MIN_CPU_PERCENT</code>, <code>MAX_CPU_PERCENT</code>, <code>MIN_MEMORY_PERCENT</code>, <code>MAX_MEMORY_PERCENT</code>, <code>MIN_IOPS_PER_VOLUME</code>, and <code>MAX_IOPS_PER_VOLUME</code>.</p> +<p>Be aware that the <code>MAX_CPU_PERCENT</code> will just "works" when there is another connection with a higher priority, otherwise it will use what is available. Let's create a pool.</p> +<div class="highlight"><pre><span></span><code><span class="k">CREATE</span><span class="w"> </span><span class="n">RESOURCE</span><span class="w"> </span><span class="n">POOL</span><span class="w"> </span><span class="o">[</span><span class="n">SpreadSheet</span><span class="o">]</span><span class="w"></span> +<span class="k">WITH</span><span class="w"> </span><span class="p">(</span><span class="w"></span> +<span class="w"> </span><span class="n">MIN_CPU_PERCENT</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">MAX_CPU_PERCENT</span><span class="o">=</span><span class="mi">20</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">MIN_MEMORY_PERCENT</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">MAX_MEMORY_PERCENT</span><span class="o">=</span><span class="mi">20</span><span class="w"></span> +<span class="p">);</span><span class="w"></span> +</code></pre></div> + +<p>## Workload Group</p> +<p>Then we have a workload group that "works" inside a pool, so you can have another granularity on how you can split your resources. Again, we have a few options: <code>IMPORTANCE</code>, <code>REQUEST_MAX_CPU_TIME_SEC</code>, <code>REQUEST_MAX_MEMORY_GRANT_PERCENT</code>, <code>GROUP_MAX_REQUESTS</code>.</p> +<p>The <code>IMPORTANCE</code> set guesses what... the importance of that workload inside the pool, you can set LOW, MEDIUM, HIGH. GROUP_MAX_REQUESTS sets how many requests can run at the same time inside that workload (0 will set as NO LIMIT)</p> +<div class="highlight"><pre><span></span><code><span class="k">CREATE</span><span class="w"> </span><span class="n">WORKLOAD</span><span class="w"> </span><span class="k">GROUP</span><span class="w"> </span><span class="o">[</span><span class="n">DepartmentA</span><span class="o">]</span><span class="w"> </span> +<span class="k">WITH</span><span class="w"> </span><span class="p">(</span><span class="w"></span> +<span class="w"> </span><span class="n">GROUP_MAX_REQUESTS</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">IMPORTANCE</span><span class="o">=</span><span class="n">LOW</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">REQUEST_MAX_CPU_TIME_SEC</span><span class="o">=</span><span class="mi">10</span><span class="p">,</span><span class="w"> </span><span class="c1">-- Time running/using CPU</span> +<span class="w"> </span><span class="n">REQUEST_MAX_MEMORY_GRANT_PERCENT</span><span class="o">=</span><span class="mi">15</span><span class="w"></span> +<span class="p">)</span><span class="w"> </span><span class="k">USING</span><span class="w"> </span><span class="o">[</span><span class="n">SpreadSheet</span><span class="o">]</span><span class="p">;</span><span class="w"> </span><span class="c1">-- pool name here</span> +</code></pre></div> + +<h2>Classifier Function</h2> +<p>This is where everything begins... This is the entry point where you should set the group name. It's a function that will run for every new connection so be aware that if your function runs lots of queries or some heavy stuff... that time will be added to the connection handshake. If the function returns NULL or a group name that doesn't exist, the 'default' group will be used... Yes, there is a default workload group where everything runs where there's no classifier.</p> +<div class="highlight"><pre><span></span><code><span class="k">CREATE</span><span class="w"> </span><span class="k">FUNCTION</span><span class="w"> </span><span class="n">fnClassWorkloadGovernor</span><span class="p">()</span><span class="w"> </span> +<span class="k">RETURNS</span><span class="w"> </span><span class="n">SYSNAME</span><span class="w"> </span><span class="k">WITH</span><span class="w"> </span><span class="n">SCHEMABINDING</span><span class="w"> </span> +<span class="k">AS</span><span class="w"> </span> +<span class="k">BEGIN</span><span class="w"> </span> +<span class="w"> </span><span class="k">IF</span><span class="w"> </span><span class="nf">APP_NAME</span><span class="p">()</span><span class="w"> </span><span class="ow">LIKE</span><span class="w"> </span><span class="s1">&#39;%Excel%&#39;</span><span class="w"></span> +<span class="w"> </span><span class="k">RETURN</span><span class="w"> </span><span class="s1">&#39;DepartmentA&#39;</span><span class="w"></span> + +<span class="w"> </span><span class="k">IF</span><span class="w"> </span><span class="nf">HOST_NAME</span><span class="p">()</span><span class="w"> </span><span class="ow">LIKE</span><span class="w"> </span><span class="s1">&#39;%THAT_MACHINE_OR_APP_SERVER%&#39;</span><span class="w"></span> +<span class="w"> </span><span class="k">RETURN</span><span class="w"> </span><span class="s1">&#39;LowPriority&#39;</span><span class="w"></span> + +<span class="w"> </span><span class="k">RETURN</span><span class="w"> </span><span class="k">NULL</span><span class="w"></span> +<span class="k">END</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> + +<span class="k">ALTER</span><span class="w"> </span><span class="n">RESOURCE</span><span class="w"> </span><span class="n">GOVERNOR</span><span class="w"> </span><span class="k">WITH</span><span class="w"> </span><span class="p">(</span><span class="n">CLASSIFIER_FUNCTION</span><span class="o">=</span><span class="n">dbo</span><span class="p">.</span><span class="n">fnClassWorkloadGovernor</span><span class="p">);</span><span class="w"></span> +<span class="k">ALTER</span><span class="w"> </span><span class="n">RESOURCE</span><span class="w"> </span><span class="n">GOVERNOR</span><span class="w"> </span><span class="k">RECONFIGURE</span><span class="p">;</span><span class="w"></span> +</code></pre></div> + +<p>There you go... now you have a fully working resource governor, but look out that If you want to delete that classifier function, first you have to remove it from the resource governor (look the SCHEMABINDING at the create up there).</p> +<p>To disable Resource Governor</p> +<div class="highlight"><pre><span></span><code><span class="k">ALTER</span><span class="w"> </span><span class="n">RESOURCE</span><span class="w"> </span><span class="n">GOVERNOR</span><span class="w"> </span><span class="k">WITH</span><span class="w"> </span><span class="p">(</span><span class="n">CLASSIFIER_FUNCTION</span><span class="o">=</span><span class="k">null</span><span class="p">)</span><span class="w"></span> +<span class="k">ALTER</span><span class="w"> </span><span class="n">RESOURCE</span><span class="w"> </span><span class="n">GOVERNOR</span><span class="w"> </span><span class="k">RECONFIGURE</span><span class="w"></span> + +<span class="k">ALTER</span><span class="w"> </span><span class="n">RESOURCE</span><span class="w"> </span><span class="n">GOVERNOR</span><span class="w"> </span><span class="n">DISABLE</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +</code></pre></div>Using git hooks to easy your life2019-07-30T20:00:00-03:002019-07-30T20:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2019-07-30:/using_git_hooks_easy_your_life.html<p>Hey folks, it's been a time since my last post. In the meantime, I moved to another state, changed job, and started learning new kinds of stuff. Today I would like to share one thing that I usually do with my small git projects. Git has many cool features, git …</p><p>Hey folks, it's been a time since my last post. In the meantime, I moved to another state, changed job, and started learning new kinds of stuff. Today I would like to share one thing that I usually do with my small git projects. Git has many cool features, git hooks were one of them. I'll talk about the pre-commit hook today.</p> +<p>Let's say that, for some reason, you don't have a CI tool/server running after every commit and you want to enforce that every developer runs the tests before every commit? Git pre-commit to the rescue. You can code the hooks with shell, ruby, python, and I could be wrong, but even PHP would work. pre-commit is a client-side hook (we have server side too) and he's located inside the <cite>.git/hooks</cite> folder. Let's jump to the code... Create a file called 'pre-commit' inside that folder with the following code.</p> +<div class="highlight"><pre><span></span><span class="ch">#!/bin/bash</span> +npm <span class="nb">test</span> <span class="c1"># assuming you&#39;re using it inside a nodeJS project</span> +</pre></div> +<p>Don't forget to make the script executable!! Now break your test and try to commit. That's easy but can save you from breaking the tests at the main CI/Travis/Codeship/etc and being notified by email :). Why not even validate the lint of your project or check if the coverage doesn't fall? Does your team/company have a patter for commit messages? No problem, there is a hook called <cite>commit-msg</cite> that you can use to validate your message.</p> +Microservices with NodeJS, Express.js and RabbitMQ Part 22018-04-13T13:00:00-03:002018-04-13T13:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-04-13:/microservices_nodejs_express_rabbitmq_part_2.html<p>If you haven't read the <a class="reference external" href="https://www.sipmann.com/microservices_nodejs_express_rabbitmq_part_1-en.html">part 1</a> go ahead and read it... It can be useful :). Or if for some reason you want to start now, you can grab the project where we stopped <a class="reference external" href="https://github.com/sipmann/imagecompacter/releases/tag/v1">here</a> and get along. On this part, we'll implement the RabbitMQ queue and see how we …</p><p>If you haven't read the <a class="reference external" href="https://www.sipmann.com/microservices_nodejs_express_rabbitmq_part_1-en.html">part 1</a> go ahead and read it... It can be useful :). Or if for some reason you want to start now, you can grab the project where we stopped <a class="reference external" href="https://github.com/sipmann/imagecompacter/releases/tag/v1">here</a> and get along. On this part, we'll implement the RabbitMQ queue and see how we can get the best of our app and server with that.</p> +<p>Before we began coding, let's understand why we are going to use RabbitMQ if what we have now works? If you check again, you'll see how long it takes to answer the request with the optimized image. It takes a few seconds, so imagine an online service with thousands of request to optimize images (like <a class="reference external" href="https://tinypng.com/">TinyPNG</a>) how long is it gonna take to answer every request? How much of your server is it gonna take? With only one service running, probably the server will crash.</p> +<p>With a queue, we can schedule the requests so we can use the amount of memory and processor that our server has, without taking more than we can. It's better to take a few seconds to answer the request then throw some error to the user. Want more? With RabbitMQ we can see how the queue is doing and we can add more consumers (workers) to it and get things done quicker and distribute the job.</p> +<p>First of all, we need an up and running Rabbit server, for the sake of simplicity, I'll use a Docker container with it inside.</p> +<div class="highlight"><pre><span></span>docker run -d --name rabbit -p <span class="m">5672</span>:5672 -p <span class="m">8080</span>:15672 rabbitmq:3-management +</pre></div> +<p>You can see that we're running the rabbitmq:3-management image, which provides us a web interface to see how things are going. After that, if you look at our code you'll see that all the job is made at the '/upload' route, and that's what we'll change.</p> +<p>First, we need to understand what we need from RabbitMQ. We need something that, we send an image to a queue and get an optimized image back from that. There is a name for that, is RPC (remote procedure call) and there are two ways of doing this with rabbit. Both the ways you can see on their tutorial page. We'll use the approach that uses a global channel whose id is randomly generated (you'll use the name 'amq.rabbitmq.reply-to' but the rabbit will do the job).</p> +<p>Let's start importing the library, defining a few variables and defining a init function that will establish a connection with the rabbit server and create our RPC queue. The RPC queue it's where we'll receive the answer from the consumer (our worker).</p> +<div class="highlight"><pre><span></span><span class="c1">//import the library</span> +<span class="kr">const</span> <span class="nx">amqplib</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;amqplib&#39;</span><span class="p">);</span> + +<span class="c1">//queue channel</span> +<span class="kd">let</span> <span class="nx">channel</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span> +<span class="c1">//queue name</span> +<span class="kr">const</span> <span class="nx">QUEUE</span> <span class="o">=</span> <span class="s1">&#39;optimizeimg&#39;</span><span class="p">;</span> + +<span class="c1">//...</span> + +<span class="kd">function</span> <span class="nx">init</span><span class="p">()</span> <span class="p">{</span> + <span class="k">return</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;amqplib&#39;</span><span class="p">).</span><span class="nx">connect</span><span class="p">(</span><span class="s1">&#39;amqp://localhost&#39;</span><span class="p">)</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">conn</span> <span class="p">=&gt;</span> <span class="nx">conn</span><span class="p">.</span><span class="nx">createChannel</span><span class="p">())</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">ch</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="nx">channel</span> <span class="o">=</span> <span class="nx">ch</span><span class="p">;</span> + + <span class="c1">//this queue is a &quot;Direct reply-to&quot; read more at the docs</span> + <span class="c1">//When some msg comes in, we &quot;emit&quot; a message to the proper &quot;correlationId&quot; listener</span> + <span class="nx">ch</span><span class="p">.</span><span class="nx">consume</span><span class="p">(</span><span class="s1">&#39;amq.rabbitmq.reply-to&#39;</span><span class="p">,</span> <span class="nx">msg</span> <span class="p">=&gt;</span> <span class="nx">eventEmitter</span><span class="p">.</span><span class="nx">emit</span><span class="p">(</span><span class="nx">msg</span><span class="p">.</span><span class="nx">properties</span><span class="p">.</span><span class="nx">correlationId</span><span class="p">,</span> <span class="nx">msg</span><span class="p">.</span><span class="nx">content</span><span class="p">),</span> <span class="p">{</span><span class="nx">noAck</span><span class="o">:</span> <span class="kc">true</span><span class="p">});</span> + <span class="p">});</span> +<span class="p">}</span> + +<span class="c1">//Random id generator</span> +<span class="kd">function</span> <span class="nx">randomid</span><span class="p">()</span> <span class="p">{</span> + <span class="k">return</span> <span class="k">new</span> <span class="nb">Date</span><span class="p">().</span><span class="nx">getTime</span><span class="p">().</span><span class="nx">toString</span><span class="p">()</span> <span class="o">+</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">random</span><span class="p">().</span><span class="nx">toString</span><span class="p">()</span> <span class="o">+</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">random</span><span class="p">().</span><span class="nx">toString</span><span class="p">();</span> +<span class="p">}</span> + +<span class="nx">app</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="s1">&#39;/upload&#39;</span><span class="p">,</span> <span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="kd">let</span> <span class="nx">img</span> <span class="o">=</span> <span class="nx">req</span><span class="p">.</span><span class="nx">files</span><span class="p">.</span><span class="nx">image</span><span class="p">;</span> + + <span class="kd">let</span> <span class="nx">id</span> <span class="o">=</span> <span class="nx">randomid</span><span class="p">();</span> + + <span class="c1">//Event listener that will fire when the proper randomid is provided</span> + <span class="nx">eventEmitter</span><span class="p">.</span><span class="nx">once</span><span class="p">(</span><span class="nx">id</span><span class="p">,</span> <span class="nx">msg</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="nx">res</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="nx">msg</span><span class="p">,</span> <span class="s1">&#39;binary&#39;</span><span class="p">);</span> + <span class="nx">res</span><span class="p">.</span><span class="nx">end</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="s1">&#39;binary&#39;</span><span class="p">);</span> + <span class="p">});</span> + + <span class="c1">//Checks if the queue exists, and create it if needed.</span> + <span class="nx">channel</span><span class="p">.</span><span class="nx">assertQueue</span><span class="p">(</span><span class="nx">QUEUE</span><span class="p">)</span> + <span class="c1">//Sent the buffered img to the queue with the ID and the responseQueue</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="nx">channel</span><span class="p">.</span><span class="nx">sendToQueue</span><span class="p">(</span><span class="nx">QUEUE</span><span class="p">,</span> <span class="nx">img</span><span class="p">.</span><span class="nx">data</span><span class="p">,</span> <span class="p">{</span><span class="nx">correlationId</span><span class="o">:</span><span class="nx">id</span><span class="p">,</span> <span class="nx">replyTo</span><span class="o">:</span> <span class="s1">&#39;amq.rabbitmq.reply-to&#39;</span><span class="p">}));</span> + +<span class="p">});</span> + +<span class="c1">//Finally start the app with the given port number</span> +<span class="c1">//now we initialize the rabbitmq connection before start the server</span> +<span class="nx">init</span><span class="p">()</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="nx">app</span><span class="p">.</span><span class="nx">listen</span><span class="p">(</span><span class="mi">4000</span><span class="p">,</span> <span class="p">()</span> <span class="p">=&gt;</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;Example app listening on port 4000!&#39;</span><span class="p">)))</span> + <span class="p">.</span><span class="k">catch</span><span class="p">(</span><span class="nx">err</span><span class="p">=&gt;</span><span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="nx">err</span><span class="p">));</span> +</pre></div> +<p>Ok, now we have our server code rewritten so let's see our worker code. Create a file named 'worker.js' and let's see how it's gonna be. It's really simple. You initialize a connection with RabbitMQ too, create a channel, check if the queue exists and start watching for incoming messages. When an image arrives, we do the job with it and send back to the &quot;replyTo&quot; queue the optimized image for the proper sender (correlationId). In the end, we do an acknowledge of the message so it get's out from the queue.</p> +<div class="highlight"><pre><span></span><span class="kr">const</span> <span class="nx">imagemin</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;imagemin&#39;</span><span class="p">);</span> +<span class="kr">const</span> <span class="nx">imageminPngquant</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;imagemin-pngquant&#39;</span><span class="p">);</span> + +<span class="kd">let</span> <span class="nx">channel</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span> +<span class="kr">const</span> <span class="nx">QUEUE</span> <span class="o">=</span> <span class="s1">&#39;imgqueue&#39;</span><span class="p">;</span> + +<span class="nx">require</span><span class="p">(</span><span class="s1">&#39;amqplib&#39;</span><span class="p">).</span><span class="nx">connect</span><span class="p">(</span><span class="s1">&#39;amqp://localhost&#39;</span><span class="p">)</span> +<span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">conn</span> <span class="p">=&gt;</span><span class="nx">conn</span><span class="p">.</span><span class="nx">createChannel</span><span class="p">())</span> +<span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">ch</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="nx">ch</span><span class="p">.</span><span class="nx">assertQueue</span><span class="p">(</span><span class="nx">QUEUE</span><span class="p">)</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="c1">//Watch incomming messages</span> + <span class="nx">ch</span><span class="p">.</span><span class="nx">consume</span><span class="p">(</span><span class="nx">QUEUE</span><span class="p">,</span> <span class="nx">msg</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="nx">imagemin</span><span class="p">.</span><span class="nx">buffer</span><span class="p">(</span><span class="nx">msg</span><span class="p">.</span><span class="nx">content</span><span class="p">,</span> <span class="p">{</span> + <span class="nx">plugins</span><span class="o">:</span> <span class="p">[</span><span class="nx">imageminPngquant</span><span class="p">()]</span> + <span class="p">})</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">out</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="c1">//Send back to the sender (replyTo) queue and give the correlationId back</span> + <span class="c1">//so we can emit the event.</span> + <span class="nx">ch</span><span class="p">.</span><span class="nx">sendToQueue</span><span class="p">(</span><span class="nx">msg</span><span class="p">.</span><span class="nx">properties</span><span class="p">.</span><span class="nx">replyTo</span><span class="p">,</span> <span class="nx">out</span><span class="p">,</span> <span class="p">{</span> + <span class="nx">correlationId</span><span class="o">:</span> <span class="nx">msg</span><span class="p">.</span><span class="nx">properties</span><span class="p">.</span><span class="nx">correlationId</span> + <span class="p">});</span> + + <span class="c1">//Acknowledge the job done with the message.</span> + <span class="nx">ch</span><span class="p">.</span><span class="nx">ack</span><span class="p">(</span><span class="nx">msg</span><span class="p">);</span> + <span class="p">});</span> + <span class="p">});</span> + <span class="p">});</span> +<span class="p">});</span> +</pre></div> +<p>The key points here are. Open just one connection to the hole server. You CAN create one channel for every request that you receive, but it can take some time if you have a really big cluster of RabbitMQ. It was a quick tutorial, but I hope that it was able to clear a few questions that you might have when working with rabbit and express.</p> +Microservices with NodeJS, Express.js and RabbitMQ Part 12018-04-04T11:25:00-03:002018-04-04T11:25:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-04-04:/microservices_nodejs_express_rabbitmq_part_1.html<p>This is the first part of a microservices development series. The service will consist of the bellow architecture, where we will expose an image optimizer service that will forward the request to a <a class="reference external" href="https://www.rabbitmq.com/">RabbitMQ</a> queue and answer with the bytecode of the optimized image. It shouldn't be a long series …</p><p>This is the first part of a microservices development series. The service will consist of the bellow architecture, where we will expose an image optimizer service that will forward the request to a <a class="reference external" href="https://www.rabbitmq.com/">RabbitMQ</a> queue and answer with the bytecode of the optimized image. It shouldn't be a long series so let's see what we can do.</p> +<img alt="Service architecture" src="/images/microservices_rabit_pt1.png" /> +<p>Let's get our environment working. First, we'll need to install the libraries that we'll use.</p> +<p>Create a dir and initialize the nodejs application inside it (<cite>npm init</cite>) and then let's install the deps.</p> +<ul class="simple"> +<li>amqplib - AMQP lib to interact with rabbitmq</li> +<li>express - Do our basic rest API</li> +<li>express-fileupload - easy file upload parser</li> +<li>imagemin and imagemin-pngquant - our image compacter</li> +</ul> +<div class="highlight"><pre><span></span>npm install --save express amqplib express-fileupload imagemin imagemin-pngquant +</pre></div> +<p>Now let's write the entry points for our service, we'll have two basic entry points. The path <cite>/</cite> that will have a welcome message, the second path will be <cite>/upload</cite> and this is the one that will handle the image and produce a job for our workers.</p> +<div class="highlight"><pre><span></span><span class="kr">const</span> <span class="nx">express</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;express&#39;</span><span class="p">);</span> +<span class="kr">const</span> <span class="nx">fileUpload</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;express-fileupload&#39;</span><span class="p">);</span> + +<span class="c1">//Instantiate the app and set the fileupload parser to manage files</span> +<span class="kr">const</span> <span class="nx">app</span> <span class="o">=</span> <span class="nx">express</span><span class="p">();</span> +<span class="nx">app</span><span class="p">.</span><span class="nx">use</span><span class="p">(</span><span class="nx">fileUpload</span><span class="p">());</span> + +<span class="c1">//Our index entry point</span> +<span class="nx">app</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;/&#39;</span><span class="p">,</span> <span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="nx">res</span><span class="p">.</span><span class="nx">send</span><span class="p">(</span><span class="s1">&#39;Hello From ImageCompacter service&#39;</span><span class="p">));</span> + +<span class="c1">//The path that will handle the image file and throw them to the queue</span> +<span class="nx">app</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="s1">&#39;/upload&#39;</span><span class="p">,</span> <span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="c1">//With express-fileupload we can grab the files like this</span> + <span class="kd">let</span> <span class="nx">img</span> <span class="o">=</span> <span class="nx">req</span><span class="p">.</span><span class="nx">files</span><span class="p">.</span><span class="nx">image</span><span class="p">;</span> <span class="c1">//&quot;image&quot; is the name of the input</span> + + <span class="nx">res</span><span class="p">.</span><span class="nx">send</span><span class="p">(</span><span class="s1">&#39;Not ready yet&#39;</span><span class="p">);</span> +<span class="p">});</span> + +<span class="c1">//Finally start the app with the given port number</span> +<span class="nx">app</span><span class="p">.</span><span class="nx">listen</span><span class="p">(</span><span class="mi">4000</span><span class="p">,</span> <span class="p">()</span> <span class="p">=&gt;</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;Example app listening on port 4000!&#39;</span><span class="p">));</span> +</pre></div> +<p>Let's check if it works, run the service with node.</p> +<div class="highlight"><pre><span></span>node index.js +Example app listening on port <span class="m">4000</span>! +</pre></div> +<p>Open the browser and check if it prints our hello message when accessing <cite>localhost:4000</cite>. Works? Greate. Now let's work with the image and see how we do it. To optimize our image, we'll use the library imagemin and <a class="reference external" href="https://www.npmjs.com/package/imagemin-pngquant">imagemin-pngquant</a>, it will be that simple for now, we'll work with rabbitmq latter.</p> +<div class="highlight"><pre><span></span><span class="kr">const</span> <span class="nx">imagemin</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;imagemin&#39;</span><span class="p">);</span> +<span class="kr">const</span> <span class="nx">imageminPngquant</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;imagemin-pngquant&#39;</span><span class="p">);</span> +<span class="c1">//...</span> + +<span class="c1">//The path that will handle the image file and throw them to the queue</span> +<span class="nx">app</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="s1">&#39;/upload&#39;</span><span class="p">,</span> <span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="kd">let</span> <span class="nx">img</span> <span class="o">=</span> <span class="nx">req</span><span class="p">.</span><span class="nx">files</span><span class="p">.</span><span class="nx">image</span><span class="p">;</span> <span class="c1">//&quot;image&quot; is the name of the input</span> + + <span class="nx">imagemin</span><span class="p">.</span><span class="nx">buffer</span><span class="p">(</span><span class="nx">img</span><span class="p">.</span><span class="nx">data</span><span class="p">,</span> <span class="p">{</span> + <span class="nx">plugins</span><span class="o">:</span> <span class="p">[</span><span class="nx">imageminPngquant</span><span class="p">()]</span> + <span class="p">})</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">out</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="nx">res</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="nx">out</span><span class="p">,</span><span class="s1">&#39;binary&#39;</span><span class="p">);</span> + <span class="nx">res</span><span class="p">.</span><span class="nx">end</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="s1">&#39;binary&#39;</span><span class="p">);</span> + <span class="p">});</span> +<span class="p">});</span> + + <span class="c1">//...</span> +</pre></div> +<p>Use <a class="reference external" href="https://www.getpostman.com/">Postman</a> to test the request. To see if it will work, make a request to <cite>http://localhost:4000/upload</cite> with a formdata with a file. Select the &quot;send and Download&quot; instead of &quot;Send&quot; and you should have an image after that. Bellow an image of how your postman should be.</p> +<img alt="Postman" src="/images/microservice_postman.png" /> +<p>That's it for today, next week we'll change our code to use RabbitMQ.</p> +Connecting to a database through SSH2018-03-29T10:03:00-03:002018-03-29T10:03:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-03-29:/connecting_to_database_through_ssh.html<p>If someday, for some reason, you need to establish a connection with a database which is behind a firewall and you only have SSH access on that server (and you don't want to use a CLI) you can do an SSH tunnel. It's pretty simple, bellow has a sample of …</p><p>If someday, for some reason, you need to establish a connection with a database which is behind a firewall and you only have SSH access on that server (and you don't want to use a CLI) you can do an SSH tunnel. It's pretty simple, bellow has a sample of how to allow connections to a remote Firebird database.</p> +<div class="highlight"><pre><span></span>ssh -L <span class="m">3051</span>:192.168.1.9:3050 username@192.168.1.9 +</pre></div> +<p>The <cite>-L</cite> parameter tells to SSH do a local port forwarding on local port <cite>3051</cite> to remote port <cite>3050</cite>. You can use it to a connection with many services, not just databases.</p> +<p>You can do the reverse kind of tunnel, forward connections from the host to your local machine, you just have to change the parameter form &quot;-L&quot; to &quot;-R&quot; and the port order is inverted, first come the port where the server will listen and after your localhost port. This remote port forwarding must be enabled on the server. Look for <cite>GatewayPorts</cite> at the ssh config file.</p> +<div class="highlight"><pre><span></span>ssh -R <span class="m">3050</span>:localhost:3050 username@192.168.1.9 +</pre></div> +<p>Why whould you need something like that?? Let's say you want to share a localhost site/database with a friend, but your internet connection don't allow you to expose any port but you have access to a remote server witch can do that. Problem solved ;).</p> +Now posting on Grepora2018-03-24T00:40:00-03:002018-03-24T00:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-03-24:/now_posting_on_grepora.html<p>A few weeks ago I started posting at <a class="reference external" href="https://grepora.com/blog/">Grepora</a> blog. If you like or are looking for some Oracle related stuff, Grepora it's a good place to go and spend a time reading :). From time to time I'll be posting there, it doesn't mean that this blog will be closed …</p><p>A few weeks ago I started posting at <a class="reference external" href="https://grepora.com/blog/">Grepora</a> blog. If you like or are looking for some Oracle related stuff, Grepora it's a good place to go and spend a time reading :). From time to time I'll be posting there, it doesn't mean that this blog will be closed or anything like that, but probably this one will be more focused on Front-end stuff, a few tricks with linux and a lil less with Java.</p> +Scaffolding a React app with Parcel and Yeoman2018-03-17T13:00:00-03:002018-03-17T13:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-03-17:/scaffolding_react_app_with_parcel_yeoman.html<p>Since <a class="reference external" href="https://parceljs.org/">Parcel JS</a> arrived, I've been using it a lot as an awesome alternative for WebPack. Webpack isn't bad but IMO it's too complex for the job and parcel do the same (at least the basic) with almost zero configuration. But if you need to create many apps (like a …</p><p>Since <a class="reference external" href="https://parceljs.org/">Parcel JS</a> arrived, I've been using it a lot as an awesome alternative for WebPack. Webpack isn't bad but IMO it's too complex for the job and parcel do the same (at least the basic) with almost zero configuration. But if you need to create many apps (like a react app) over and over again, it get's a lil boring following the basic steps.</p> +<div class="highlight"><pre><span></span>npm init -y +npm install --save react +npm install --save react-dom +npm install --save-dev parcel-bundler +npm install --save-dev babel-preset-env +npm install --save-dev babel-preset-react + +<span class="c1">#create .babelrc file</span> +<span class="c1">#create html, css, jsx files</span> + +parcel index.html +</pre></div> +<p>It's not a hard job, a simple shell script do the job, but what if you need some IFs when creating the app, or even change a few things at the <cite>package.json</cite>? A shell script still does the job, but come on... There is a better way. <a class="reference external" href="http://yeoman.io/">Yeoman</a> is here for you. I've already <a class="reference external" href="https://www.sipmann.com/desenvolvendo-app-firefoxos-pt.html">talked about it</a> on another post (Portuguese post).</p> +<p>Straight to the point, I've released a Yeoman generator to get the things a lil quicker. The name is <a class="reference external" href="https://www.npmjs.com/package/generator-parcel-react">generator-parcel-react</a> and it still lacks a few things that I will deal with soon. It's pretty simple to use it.</p> +<div class="highlight"><pre><span></span><span class="c1">#First time only</span> +npm install -g yo +npm install -g generator-parcel-react + +<span class="c1">#every time you create a new app</span> +yo parcel-react +</pre></div> +<p>And that's it. Right now you can scaffold and app with React, SASS and React Router. Hope you like it and feel free to ask new features.</p> +Could not open connection with MySQL and Hibernate2018-03-09T12:35:00-03:002018-03-09T12:35:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-03-09:/cloud-not-open-connection-java-mysql-hibernate.html<p>Last day I decided to deploy a MySQL Docker image to work with my Java application. I've been using PostgreSQL instead and have no problems at all, but after I moved to MySQL, the app didn't connect anymore with the database and throw some &quot;Could not open connection&quot; at my …</p><p>Last day I decided to deploy a MySQL Docker image to work with my Java application. I've been using PostgreSQL instead and have no problems at all, but after I moved to MySQL, the app didn't connect anymore with the database and throw some &quot;Could not open connection&quot; at my face, but why? I've tried to connect to it manually and got the same problem.</p> +<p>After some research, I found that the true error should be java.sql.SQLException: null, message from server: &quot;Host '172.17.0.4' is not allowed to connect to this MySQL server&quot; but it wasn't showing to me...</p> +<p>After all, be aware that with the docker image MySQL:5.7.21 (latest version right now) the root user isn't allowed to remote connect to the database (it's alright, security reasons) and if you still want to do remote connections to it with root there are a few things you can do.</p> +<ol class="arabic simple"> +<li>Create a user or allow root to access from other IPs.</li> +</ol> +<div class="highlight"><pre><span></span><span class="o">#</span><span class="k">No</span> <span class="k">access</span> <span class="k">to</span> <span class="k">user</span> <span class="n">root</span> <span class="k">on</span> <span class="k">any</span> <span class="n">other</span> <span class="n">IP</span> +<span class="k">SELECT</span> <span class="k">User</span><span class="p">,</span> <span class="k">Host</span> <span class="k">FROM</span> <span class="n">mysql</span><span class="p">.</span><span class="k">user</span><span class="p">;</span> +<span class="o">+</span><span class="c1">---------------+-----------+</span> +<span class="o">|</span> <span class="k">User</span> <span class="o">|</span> <span class="k">Host</span> <span class="o">|</span> +<span class="o">+</span><span class="c1">---------------+-----------+</span> +<span class="o">|</span> <span class="n">healthchecker</span> <span class="o">|</span> <span class="n">localhost</span> <span class="o">|</span> +<span class="o">|</span> <span class="n">root</span> <span class="o">|</span> <span class="n">localhost</span> <span class="o">|</span> +<span class="o">+</span><span class="c1">---------------+-----------+</span> +<span class="mi">2</span> <span class="k">rows</span> <span class="k">in</span> <span class="k">set</span> <span class="p">(</span><span class="mi">0</span><span class="p">.</span><span class="mi">01</span> <span class="n">sec</span><span class="p">)</span> + +<span class="k">CREATE</span> <span class="k">USER</span> <span class="s1">&#39;newuser&#39;</span><span class="o">@</span><span class="s1">&#39;%&#39;</span> <span class="n">IDENTIFIED</span> <span class="k">BY</span> <span class="s1">&#39;password&#39;</span><span class="p">;</span> <span class="o">#%</span> <span class="n">mean</span> <span class="k">any</span> <span class="n">IP</span> +<span class="k">GRANT</span> <span class="k">ALL</span> <span class="k">PRIVILEGES</span> <span class="k">ON</span> <span class="o">*</span><span class="p">.</span><span class="o">*</span> <span class="k">TO</span> <span class="s1">&#39;newuser&#39;</span><span class="o">@</span><span class="s1">&#39;%&#39;</span><span class="p">;</span> <span class="o">#*</span><span class="p">.</span><span class="o">*</span> <span class="n">mean</span> <span class="k">database</span><span class="p">.</span><span class="k">table</span> <span class="p">;)</span> +</pre></div> +<ol class="arabic simple" start="2"> +<li>Use MariaDB instead, witch come (at least on the version 10.2.13) with root allowed to do remote connections and will work like MySQL :)</li> +</ol> +<p>I changed to <a class="reference external" href="https://mariadb.org/">MariaDB</a> as it work without creating user or any changes on the Java code or the <cite>docker run command</cite>.</p> +Solving java.net.SocketException: Protocol family unavailable on a Java + Docker + WildFly2018-03-04T17:40:00-03:002018-03-04T17:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-03-04:/socketException-protocol-family-unavailable-java-docker-wildfly.html<p>On the last days I've been playing with <a class="reference external" href="http://wildfly-swarm.io/">WildFly Swarm</a> and I decided to deploy a simple app with Docker. Should work fine, at least that was what I thought. Built a container with the following Dockerfile and instead of a working web app, all that I got was the …</p><p>On the last days I've been playing with <a class="reference external" href="http://wildfly-swarm.io/">WildFly Swarm</a> and I decided to deploy a simple app with Docker. Should work fine, at least that was what I thought. Built a container with the following Dockerfile and instead of a working web app, all that I got was the error <cite>java.net.SocketException: Protocol family unavailable</cite>.</p> +<div class="highlight"><pre><span></span><span class="k">FROM</span> <span class="s">java:openjdk-8-jdk</span> + +<span class="k">COPY</span> target/issues.jar /opt/issues.jar + +<span class="k">EXPOSE</span><span class="s"> 8080</span> + +<span class="k">CMD</span> <span class="p">[</span><span class="s2">&quot;java&quot;</span><span class="p">,</span><span class="s2">&quot;-jar&quot;</span><span class="p">,</span><span class="s2">&quot;/opt/issues.jar&quot;</span><span class="p">]</span> +</pre></div> +<p>For some reason, WildFly and Java decided to use the IPv6 network interface from Docker instead the v4, so all you have to do is tell Java to prefer IPv4 instead with the following configuration option in your pom.xml file inside your WildFly plugin.</p> +<div class="highlight"><pre><span></span><span class="nt">&lt;plugin&gt;</span> + <span class="nt">&lt;groupId&gt;</span>org.wildfly.swarm<span class="nt">&lt;/groupId&gt;</span> + <span class="nt">&lt;artifactId&gt;</span>wildfly-swarm-plugin<span class="nt">&lt;/artifactId&gt;</span> + <span class="nt">&lt;version&gt;</span>2018.2.0<span class="nt">&lt;/version&gt;</span> + + <span class="c">&lt;!-- ADD THIS --&gt;</span> + <span class="nt">&lt;configuration&gt;</span> + <span class="nt">&lt;mainClass&gt;</span>org.wildfly.swarm.examples.netflix.ribbon.frontend.Main<span class="nt">&lt;/mainClass&gt;</span> + <span class="nt">&lt;properties&gt;</span> + <span class="nt">&lt;java.net.preferIPv4Stack&gt;</span>true<span class="nt">&lt;/java.net.preferIPv4Stack&gt;</span> + <span class="nt">&lt;/properties&gt;</span> + <span class="nt">&lt;/configuration&gt;</span> +</pre></div> +<p>Another way to solve is adding the same properties to the run command at the Dockerfile, so you choose where you'll add it. Bellow the Dockerfile solution.</p> +<div class="highlight"><pre><span></span><span class="k">FROM</span> <span class="s">java:openjdk-8-jdk</span> +<span class="k">ENV</span> <span class="nv">JAVA_OPTS</span><span class="o">=</span><span class="s2">&quot;-Djava.net.preferIPv4Stack=true -Djava.net.preferIPv4Addresses=true&quot;</span> + +<span class="k">COPY</span> target/issues.jar /opt/issues.jar + +<span class="k">EXPOSE</span><span class="s"> 8080</span> + +<span class="k">ENTRYPOINT</span> <span class="nb">exec</span> java <span class="nv">$JAVA_OPTS</span> -jar /opt/issues.jar +</pre></div> +Resolvendo java.net.SocketException: Protocol family unavailable em Java + Docker + WildFly2018-03-04T17:40:00-03:002018-03-04T17:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-03-04:/pt/socketException-protocol-family-unavailable-java-docker-wildfly.html<p>Nos últimos dias eu estou brincando com o <a class="reference external" href="http://wildfly-swarm.io/">WildFly Swarm</a> e decidi fazer o deploy de uma aplicação simples com Docker. Deveria funcionar bem, ao menos é o que pensava. Construí um container com o seguinte Dockerfile e ao invés de obter uma aplicação web, tudo que eu obtive foi …</p><p>Nos últimos dias eu estou brincando com o <a class="reference external" href="http://wildfly-swarm.io/">WildFly Swarm</a> e decidi fazer o deploy de uma aplicação simples com Docker. Deveria funcionar bem, ao menos é o que pensava. Construí um container com o seguinte Dockerfile e ao invés de obter uma aplicação web, tudo que eu obtive foi o erro <cite>java.net.SocketException: Protocol family unavailable</cite>.</p> +<div class="highlight"><pre><span></span><span class="k">FROM</span> <span class="s">java:openjdk-8-jdk</span> + +<span class="k">COPY</span> target/issues.jar /opt/issues.jar + +<span class="k">EXPOSE</span><span class="s"> 8080</span> + +<span class="k">CMD</span> <span class="p">[</span><span class="s2">&quot;java&quot;</span><span class="p">,</span><span class="s2">&quot;-jar&quot;</span><span class="p">,</span><span class="s2">&quot;/opt/issues.jar&quot;</span><span class="p">]</span> +</pre></div> +<p>Por alguma razão, WildFly e Java, ambos decidiram utilizar um protocolo IPv6 na interface de rede no Docker invés da v4, então tudo que você tem que fazer é falar ao Java que deve dar preferência em utilizar o IPv4 com a seguinte configuração no seu arquivo pom.xml dentro da tag do plugin WildFly.</p> +<div class="highlight"><pre><span></span><span class="nt">&lt;plugin&gt;</span> + <span class="nt">&lt;groupId&gt;</span>org.wildfly.swarm<span class="nt">&lt;/groupId&gt;</span> + <span class="nt">&lt;artifactId&gt;</span>wildfly-swarm-plugin<span class="nt">&lt;/artifactId&gt;</span> + <span class="nt">&lt;version&gt;</span>2018.2.0<span class="nt">&lt;/version&gt;</span> + + <span class="c">&lt;!-- ADICIONE ISTO --&gt;</span> + <span class="nt">&lt;configuration&gt;</span> + <span class="nt">&lt;mainClass&gt;</span>org.wildfly.swarm.examples.netflix.ribbon.frontend.Main<span class="nt">&lt;/mainClass&gt;</span> + <span class="nt">&lt;properties&gt;</span> + <span class="nt">&lt;java.net.preferIPv4Stack&gt;</span>true<span class="nt">&lt;/java.net.preferIPv4Stack&gt;</span> + <span class="nt">&lt;/properties&gt;</span> + <span class="nt">&lt;/configuration&gt;</span> +</pre></div> +<p>Outra forma de solucionar o problema, é adicionando a mesma propriedade ao comando de run no seu Dockerfile. Então, fica a seu critério onde adicionar. Abaixo a solução utilizando o Dockerfile.</p> +<div class="highlight"><pre><span></span><span class="k">FROM</span> <span class="s">java:openjdk-8-jdk</span> +<span class="k">ENV</span> <span class="nv">JAVA_OPTS</span><span class="o">=</span><span class="s2">&quot;-Djava.net.preferIPv4Stack=true -Djava.net.preferIPv4Addresses=true&quot;</span> + +<span class="k">COPY</span> target/issues.jar /opt/issues.jar + +<span class="k">EXPOSE</span><span class="s"> 8080</span> + +<span class="k">ENTRYPOINT</span> <span class="nb">exec</span> java <span class="nv">$JAVA_OPTS</span> -jar /opt/issues.jar +</pre></div> +Change display settings on linux with Disper2018-02-27T12:40:00-03:002018-02-27T12:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-02-27:/linux-external-display-with-disper.html<p>From time to time, I change the Linux distro on my laptop or just do a fresh install on it. And once in a while, have random problems with external displays. It can be something really &quot;simple&quot; like don't detecting the external monitor or something crazy like the image below …</p><p>From time to time, I change the Linux distro on my laptop or just do a fresh install on it. And once in a while, have random problems with external displays. It can be something really &quot;simple&quot; like don't detecting the external monitor or something crazy like the image below.</p> +<img alt="Display bug" src="/images/bug.png" /> +<p>As you can see at the image, the mint detected the display but mirrored it in a crazy way that works but doesn't at the same time. If you try anything and doesn't get working, or just wanna skip the whole job of configuring complexes text files, give a try to <a class="reference external" href="http://willem.engen.nl/projects/disper/">Disper</a>. Download the latest version. +Extract it on any folder, and make install it (on the extracted folder).</p> +<div class="highlight"><pre><span></span>make install +</pre></div> +<p>After that, you can start using it... There are a few options that will serve you well.</p> +<div class="highlight"><pre><span></span>disper -e <span class="c1">#extend your display</span> +</pre></div> +<div class="highlight"><pre><span></span>disper -c <span class="c1">#clone your display</span> +</pre></div> +<div class="highlight"><pre><span></span>disper -s <span class="c1">#only your external display</span> +</pre></div> +Java - Files.readAllBytes throws OutOfMemory2018-02-17T13:00:00-02:002018-02-17T13:00:00-02:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-02-17:/reading-files-java-readAllBytes-outofmemory.html<p>When you need to interact with files, there's the possibility to read all bytes from the file with <cite>Files.readAllBytes</cite>. But be aware of the kinds of files your application will deal with because the Java API files have a limit for the buffer that is defined as <cite>Integer.MAX_VALUE …</cite></p><p>When you need to interact with files, there's the possibility to read all bytes from the file with <cite>Files.readAllBytes</cite>. But be aware of the kinds of files your application will deal with because the Java API files have a limit for the buffer that is defined as <cite>Integer.MAX_VALUE</cite> as you can see above or at the OpenJDK sources.</p> +<div class="highlight"><pre><span></span><span class="kd">public</span> <span class="kd">static</span> <span class="kt">byte</span><span class="o">[]</span> <span class="nf">readAllBytes</span><span class="p">(</span><span class="n">Path</span> <span class="n">path</span><span class="p">)</span> <span class="kd">throws</span> <span class="n">IOException</span> <span class="p">{</span> + <span class="k">try</span> <span class="p">(</span><span class="n">FileChannel</span> <span class="n">fc</span> <span class="o">=</span> <span class="n">FileChannel</span><span class="p">.</span><span class="na">open</span><span class="p">(</span><span class="n">path</span><span class="p">))</span> <span class="p">{</span> + <span class="kt">long</span> <span class="n">size</span> <span class="o">=</span> <span class="n">fc</span><span class="p">.</span><span class="na">size</span><span class="p">();</span> + <span class="k">if</span> <span class="p">(</span><span class="n">size</span> <span class="o">&gt;</span> <span class="p">(</span><span class="kt">long</span><span class="p">)</span><span class="n">Integer</span><span class="p">.</span><span class="na">MAX_VALUE</span><span class="p">)</span> + <span class="k">throw</span> <span class="k">new</span> <span class="n">OutOfMemoryError</span><span class="p">(</span><span class="s">&quot;Required array size too large&quot;</span><span class="p">);</span> + + <span class="kt">byte</span><span class="o">[]</span> <span class="n">arr</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">byte</span><span class="o">[</span><span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">size</span><span class="o">]</span><span class="p">;</span> + <span class="n">ByteBuffer</span> <span class="n">bb</span> <span class="o">=</span> <span class="n">ByteBuffer</span><span class="p">.</span><span class="na">wrap</span><span class="p">(</span><span class="n">arr</span><span class="p">);</span> + <span class="k">while</span> <span class="p">(</span><span class="n">bb</span><span class="p">.</span><span class="na">hasRemaining</span><span class="p">())</span> <span class="p">{</span> + <span class="k">if</span> <span class="p">(</span><span class="n">fc</span><span class="p">.</span><span class="na">read</span><span class="p">(</span><span class="n">bb</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> + <span class="c1">// truncated</span> + <span class="k">break</span><span class="p">;</span> + <span class="p">}</span> + <span class="p">}</span> + + <span class="kt">int</span> <span class="n">nread</span> <span class="o">=</span> <span class="n">bb</span><span class="p">.</span><span class="na">position</span><span class="p">();</span> + <span class="k">return</span> <span class="p">(</span><span class="n">nread</span> <span class="o">==</span> <span class="n">size</span><span class="p">)</span> <span class="o">?</span> <span class="n">arr</span> <span class="p">:</span> <span class="n">Arrays</span><span class="p">.</span><span class="na">copyOf</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="n">nread</span><span class="p">);</span> + <span class="p">}</span> +<span class="p">}</span> +</pre></div> +<p>With that in mind, check if isn't better read chunks of bytes e work with that slice in exchange of loading the whole file into the memory ;). Above a simple example of how you can read chunks of bytes from the file.</p> +<div class="highlight"><pre><span></span><span class="kt">byte</span><span class="o">[]</span> <span class="n">buffer</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">byte</span><span class="o">[</span><span class="mi">1024</span><span class="o">]</span><span class="p">;</span> +<span class="n">FileInputStream</span> <span class="n">in</span> <span class="o">=</span> <span class="k">new</span> <span class="n">FileInputStream</span><span class="p">(</span><span class="n">file</span><span class="p">);</span> +<span class="kt">int</span> <span class="n">rc</span> <span class="o">=</span> <span class="n">in</span><span class="p">.</span><span class="na">read</span><span class="p">(</span><span class="n">buffer</span><span class="p">);</span> +<span class="k">while</span> <span class="p">(</span><span class="n">rc</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span> +<span class="p">{</span> + <span class="c1">//crazy stuff here with buffer</span> + <span class="n">rc</span> <span class="o">=</span> <span class="n">in</span><span class="p">.</span><span class="na">read</span><span class="p">(</span><span class="n">buffer</span><span class="p">);</span> +<span class="p">}</span> +</pre></div> + \ No newline at end of file diff --git a/feeds/all.atom.xml.gz b/feeds/all.atom.xml.gz new file mode 100644 index 000000000..151022707 Binary files /dev/null and b/feeds/all.atom.xml.gz differ diff --git a/feeds/azure.atom.xml b/feeds/azure.atom.xml new file mode 100644 index 000000000..4741122a6 --- /dev/null +++ b/feeds/azure.atom.xml @@ -0,0 +1,52 @@ + +Sipmann - Azurehttps://www.sipmann.com/2020-10-03T19:00:00-03:00Microsoft Against Covid2020-10-03T19:00:00-03:002020-10-03T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-03:/microsoft-against-covid.html<p>Has your job been affected by covid? Well, last week I've posted on <a href="https://grepora.com/2020/09/17/microsoft-ignite-certification-voucher/">Grepora</a> about a Free Certification Voucher that Microsoft was giving away at the Microsoft Ignite event. After that, I found that they were also giving a huge discount to people who have had their job affected by …</p><p>Has your job been affected by covid? Well, last week I've posted on <a href="https://grepora.com/2020/09/17/microsoft-ignite-certification-voucher/">Grepora</a> about a Free Certification Voucher that Microsoft was giving away at the Microsoft Ignite event. After that, I found that they were also giving a huge discount to people who have had their job affected by covid pandemic. </p> +<p>To see more details about if you were eligible, access <a href="https://docs.microsoft.com/en-us/learn/certifications/skillingoffer">https://docs.microsoft.com/en-us/learn/certifications/skillingoffer</a>.</p>Monitoring a Website heath with Azure Functions2020-06-22T19:00:00-03:002020-06-22T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-06-22:/monitoring-website-heath-with-azure-functions.html<p>Sometimes you get your self in need to monitor a website's health or it's content for changes. Of course, there's plenty of options out there, but for the sake of curiosity, let's code our own to see what we can do. First things first. Everything you'll see here, you can …</p><p>Sometimes you get your self in need to monitor a website's health or it's content for changes. Of course, there's plenty of options out there, but for the sake of curiosity, let's code our own to see what we can do. First things first. Everything you'll see here, you can achieve with the <a href="https://azure.microsoft.com/free/">free tier</a> of azure.</p> +<p>The main idea of our app will be to monitor website health (status code). To create a new Azure Function Project, follow the steps below.</p> +<p><img alt="Steps to create a azure function project" src="/images/azure_functions.gif"></p> +<p>After creating the project, you'll have a few files. Open your main file and start coding. The main file will have a function called <code>Run</code> and you can code your request method. I've created an <code>async</code> method to make the request and log the output at the console. The full code you can see below.</p> +<div class="highlight"><pre><span></span><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Linq</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Net.Http</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Threading.Tasks</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">Microsoft.Azure.WebJobs</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">Microsoft.Azure.WebJobs.Host</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">Microsoft.Extensions.Logging</span><span class="p">;</span> + +<span class="k">namespace</span> <span class="nn">Sipmann.CheckMySite</span> +<span class="p">{</span> + <span class="k">public</span> <span class="k">static</span> <span class="k">class</span> <span class="nc">HttpCheck</span> + <span class="p">{</span> + + <span class="k">private</span> <span class="k">static</span> <span class="k">async</span> <span class="n">Task</span> <span class="nf">GetTask</span><span class="p">(</span><span class="kt">string</span> <span class="n">url</span><span class="p">,</span> <span class="n">ILogger</span> <span class="n">log</span><span class="p">)</span> + <span class="p">{</span> + <span class="kt">var</span> <span class="n">request</span> <span class="p">=</span> <span class="k">new</span> <span class="n">HttpRequestMessage</span><span class="p">(</span><span class="n">HttpMethod</span><span class="p">.</span><span class="n">Get</span><span class="p">,</span> <span class="n">url</span><span class="p">);</span> + + <span class="kt">var</span> <span class="n">client</span> <span class="p">=</span> <span class="k">new</span> <span class="n">HttpClient</span><span class="p">();</span> + <span class="kt">var</span> <span class="n">response</span> <span class="p">=</span> <span class="k">await</span> <span class="n">client</span><span class="p">.</span><span class="n">SendAsync</span><span class="p">(</span><span class="n">request</span><span class="p">);</span> + + <span class="k">if</span> <span class="p">(</span><span class="n">response</span><span class="p">.</span><span class="n">IsSuccessStatusCode</span><span class="p">)</span> + <span class="p">{</span> + <span class="n">log</span><span class="p">.</span><span class="n">LogInformation</span><span class="p">(</span><span class="err">$</span><span class="s">&quot;URL ${url} esta OK&quot;</span><span class="p">);</span> + <span class="p">}</span> + <span class="k">else</span> + <span class="p">{</span> + <span class="n">log</span><span class="p">.</span><span class="n">LogInformation</span><span class="p">(</span><span class="err">$</span><span class="s">&quot;URL ${url} não esta OK&quot;</span><span class="p">);</span> + <span class="p">}</span> + <span class="p">}</span> + +<span class="na"> [FunctionName(&quot;HttpCheck&quot;)]</span> + <span class="k">public</span> <span class="k">static</span> <span class="k">void</span> <span class="nf">Run</span><span class="p">([</span><span class="n">TimerTrigger</span><span class="p">(</span><span class="s">&quot;0 */5 * * * *&quot;</span><span class="p">)]</span><span class="n">TimerInfo</span> <span class="n">myTimer</span><span class="p">,</span> <span class="n">ILogger</span> <span class="n">log</span><span class="p">)</span> + <span class="p">{</span> + <span class="kt">var</span> <span class="n">urls</span> <span class="p">=</span> <span class="k">new</span><span class="p">[]{</span><span class="s">&quot;https://www.sipmann.com&quot;</span><span class="p">,</span> <span class="s">&quot;https://www.canezecanez.com.br&quot;</span><span class="p">};</span> + + <span class="c1">// Start every request and wait for them all to complete</span> + <span class="n">Task</span><span class="p">.</span><span class="n">WaitAll</span><span class="p">(</span><span class="n">urls</span><span class="p">.</span><span class="n">Select</span><span class="p">(</span><span class="n">url</span> <span class="p">=&gt;</span> <span class="n">GetTask</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">log</span><span class="p">)).</span><span class="n">ToArray</span><span class="p">());</span> + <span class="n">log</span><span class="p">.</span><span class="n">LogInformation</span><span class="p">(</span><span class="err">$</span><span class="s">&quot;Finalizou a fila&quot;</span><span class="p">);</span> + <span class="p">}</span> + <span class="p">}</span> +<span class="p">}</span> +</code></pre></div> + +<p>Now you can enhance the function and maybe send some alerts like a Telegram message when one of your sites went down.</p>Azure Data Fundamentals certification with 80% discount2020-06-09T12:30:00-03:002020-06-09T12:30:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-06-09:/azure-data-fundamentals-certification-80-discount.html<p>Hey folks, if you want to achieve some certification this year, keep an eye open for vouchers. A few months ago, Oracle released a set of free courses with certifications. Now it's Microsoft time. Microsoft is updating they're certifications and we have a voucher of 80% discount using the coupon …</p><p>Hey folks, if you want to achieve some certification this year, keep an eye open for vouchers. A few months ago, Oracle released a set of free courses with certifications. Now it's Microsoft time. Microsoft is updating they're certifications and we have a voucher of 80% discount using the coupon <strong>DP900Norfolk</strong> at the checkout of the beta certification DP-900. </p> +<p>Be aware that this certification is in beta and the result won't be instantly available as the regular ones. Access the following link and schedule your exam. <a href="https://docs.microsoft.com/pt-br/learn/certifications/exams/dp-900" target="_blank">https://docs.microsoft.com/pt-br/learn/certifications/exams/dp-900</a>.</p> +<p><strong>Update:</strong> There is a 80% voucher also for <a href="https://docs.microsoft.com/en-us/learn/certifications/azure-ai-fundamentals" target="_blank">https://docs.microsoft.com/en-us/learn/certifications/azure-ai-fundamentals</a>. Voucher: <strong>AI900Saratoga</strong></p> \ No newline at end of file diff --git a/feeds/azure.atom.xml.gz b/feeds/azure.atom.xml.gz new file mode 100644 index 000000000..60060d193 Binary files /dev/null and b/feeds/azure.atom.xml.gz differ diff --git a/feeds/flutter.atom.xml b/feeds/flutter.atom.xml new file mode 100644 index 000000000..5a450e645 --- /dev/null +++ b/feeds/flutter.atom.xml @@ -0,0 +1,28 @@ + +Sipmann - Flutterhttps://www.sipmann.com/2019-10-03T19:00:00-03:00Flutter + firebase auth crashing2019-10-03T19:00:00-03:002019-10-03T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2019-10-03:/flutter_with_firebase_auth_crashing.html<p>Hey Folks, recently I've started learning <a href="https://flutter.dev/">Flutter</a> and right after a TODO List, I tried a Firebase integration. But as soon as I started setting the dependencies, my app stopped opening... just a crash. After a few logs digging, I've found the following log.</p> +<div class="highlight"><pre><span></span><code>AndroidRuntime: FATAL EXCEPTION: main +AndroidRuntime: Process …</code></pre></div><p>Hey Folks, recently I've started learning <a href="https://flutter.dev/">Flutter</a> and right after a TODO List, I tried a Firebase integration. But as soon as I started setting the dependencies, my app stopped opening... just a crash. After a few logs digging, I've found the following log.</p> +<div class="highlight"><pre><span></span><code>AndroidRuntime: FATAL EXCEPTION: main +AndroidRuntime: Process: com.example.diadocasal, PID: <span class="m">13672</span> +AndroidRuntime: java.lang.NoClassDefFoundError: Failed resolution of: Landroid/support/v4/util/ArrayMap<span class="p">;</span> +AndroidRuntime: at com.google.android.gms.internal.measurement.zzca.&lt;clinit&gt;<span class="o">(</span>Unknown Source:60<span class="o">)</span> +AndroidRuntime: at com.google.android.gms.internal.measurement.zzcm.zzr<span class="o">(</span>Unknown Source:7<span class="o">)</span> +AndroidRuntime: at com.google.android.gms.measurement.internal.zzfj.&lt;init&gt;<span class="o">(</span>Unknown Source:23<span class="o">)</span> +</code></pre></div> + +<p>Notice the "NoClassDefFound" of an ArrayMap. To solve that I did the following changes to the files:</p> +<div class="highlight"><pre><span></span><code><span class="c1">//build.gradle file</span> + <span class="n">ext</span><span class="p">.</span><span class="na">kotlin_version</span> <span class="o">=</span> <span class="err">&#39;</span><span class="mf">1.3.20</span><span class="err">&#39;</span> +<span class="o">[</span><span class="p">...</span><span class="o">]</span> + <span class="n">dependencies</span> <span class="p">{</span> + <span class="n">classpath</span> <span class="err">&#39;</span><span class="n">com</span><span class="p">.</span><span class="na">android</span><span class="p">.</span><span class="na">tools</span><span class="p">.</span><span class="na">build</span><span class="p">:</span><span class="n">gradle</span><span class="p">:</span><span class="mf">3.3.0</span><span class="err">&#39;</span> <span class="c1">// gradle version</span> +</code></pre></div> + +<div class="highlight"><pre><span></span><code><span class="c1">;gradle.properties file</span> +<span class="na">org.gradle.jvmargs</span><span class="o">=</span><span class="s">-Xmx1536M ;mine have just this line at first</span> +<span class="na">android.useAndroidX</span><span class="o">=</span><span class="s">true ; uses androidX instead of the default support library</span> +<span class="na">android.enableJetifier</span><span class="o">=</span><span class="s">true ; uses jetpack libraries</span> +<span class="na">android.enableR8</span><span class="o">=</span><span class="s">true ; the new code shriker</span> +</code></pre></div> + +<p>After that, voilà, app up and running.</p> \ No newline at end of file diff --git a/feeds/flutter.atom.xml.gz b/feeds/flutter.atom.xml.gz new file mode 100644 index 000000000..1e4f7da06 Binary files /dev/null and b/feeds/flutter.atom.xml.gz differ diff --git a/feeds/front-end.atom.xml b/feeds/front-end.atom.xml new file mode 100644 index 000000000..020ecf405 --- /dev/null +++ b/feeds/front-end.atom.xml @@ -0,0 +1,178 @@ + +Sipmann - Front-endhttps://www.sipmann.com/2018-04-13T13:00:00-03:00Microservices with NodeJS, Express.js and RabbitMQ Part 22018-04-13T13:00:00-03:002018-04-13T13:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-04-13:/microservices_nodejs_express_rabbitmq_part_2.html<p>If you haven't read the <a class="reference external" href="https://www.sipmann.com/microservices_nodejs_express_rabbitmq_part_1-en.html">part 1</a> go ahead and read it... It can be useful :). Or if for some reason you want to start now, you can grab the project where we stopped <a class="reference external" href="https://github.com/sipmann/imagecompacter/releases/tag/v1">here</a> and get along. On this part, we'll implement the RabbitMQ queue and see how we …</p><p>If you haven't read the <a class="reference external" href="https://www.sipmann.com/microservices_nodejs_express_rabbitmq_part_1-en.html">part 1</a> go ahead and read it... It can be useful :). Or if for some reason you want to start now, you can grab the project where we stopped <a class="reference external" href="https://github.com/sipmann/imagecompacter/releases/tag/v1">here</a> and get along. On this part, we'll implement the RabbitMQ queue and see how we can get the best of our app and server with that.</p> +<p>Before we began coding, let's understand why we are going to use RabbitMQ if what we have now works? If you check again, you'll see how long it takes to answer the request with the optimized image. It takes a few seconds, so imagine an online service with thousands of request to optimize images (like <a class="reference external" href="https://tinypng.com/">TinyPNG</a>) how long is it gonna take to answer every request? How much of your server is it gonna take? With only one service running, probably the server will crash.</p> +<p>With a queue, we can schedule the requests so we can use the amount of memory and processor that our server has, without taking more than we can. It's better to take a few seconds to answer the request then throw some error to the user. Want more? With RabbitMQ we can see how the queue is doing and we can add more consumers (workers) to it and get things done quicker and distribute the job.</p> +<p>First of all, we need an up and running Rabbit server, for the sake of simplicity, I'll use a Docker container with it inside.</p> +<div class="highlight"><pre><span></span>docker run -d --name rabbit -p <span class="m">5672</span>:5672 -p <span class="m">8080</span>:15672 rabbitmq:3-management +</pre></div> +<p>You can see that we're running the rabbitmq:3-management image, which provides us a web interface to see how things are going. After that, if you look at our code you'll see that all the job is made at the '/upload' route, and that's what we'll change.</p> +<p>First, we need to understand what we need from RabbitMQ. We need something that, we send an image to a queue and get an optimized image back from that. There is a name for that, is RPC (remote procedure call) and there are two ways of doing this with rabbit. Both the ways you can see on their tutorial page. We'll use the approach that uses a global channel whose id is randomly generated (you'll use the name 'amq.rabbitmq.reply-to' but the rabbit will do the job).</p> +<p>Let's start importing the library, defining a few variables and defining a init function that will establish a connection with the rabbit server and create our RPC queue. The RPC queue it's where we'll receive the answer from the consumer (our worker).</p> +<div class="highlight"><pre><span></span><span class="c1">//import the library</span> +<span class="kr">const</span> <span class="nx">amqplib</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;amqplib&#39;</span><span class="p">);</span> + +<span class="c1">//queue channel</span> +<span class="kd">let</span> <span class="nx">channel</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span> +<span class="c1">//queue name</span> +<span class="kr">const</span> <span class="nx">QUEUE</span> <span class="o">=</span> <span class="s1">&#39;optimizeimg&#39;</span><span class="p">;</span> + +<span class="c1">//...</span> + +<span class="kd">function</span> <span class="nx">init</span><span class="p">()</span> <span class="p">{</span> + <span class="k">return</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;amqplib&#39;</span><span class="p">).</span><span class="nx">connect</span><span class="p">(</span><span class="s1">&#39;amqp://localhost&#39;</span><span class="p">)</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">conn</span> <span class="p">=&gt;</span> <span class="nx">conn</span><span class="p">.</span><span class="nx">createChannel</span><span class="p">())</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">ch</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="nx">channel</span> <span class="o">=</span> <span class="nx">ch</span><span class="p">;</span> + + <span class="c1">//this queue is a &quot;Direct reply-to&quot; read more at the docs</span> + <span class="c1">//When some msg comes in, we &quot;emit&quot; a message to the proper &quot;correlationId&quot; listener</span> + <span class="nx">ch</span><span class="p">.</span><span class="nx">consume</span><span class="p">(</span><span class="s1">&#39;amq.rabbitmq.reply-to&#39;</span><span class="p">,</span> <span class="nx">msg</span> <span class="p">=&gt;</span> <span class="nx">eventEmitter</span><span class="p">.</span><span class="nx">emit</span><span class="p">(</span><span class="nx">msg</span><span class="p">.</span><span class="nx">properties</span><span class="p">.</span><span class="nx">correlationId</span><span class="p">,</span> <span class="nx">msg</span><span class="p">.</span><span class="nx">content</span><span class="p">),</span> <span class="p">{</span><span class="nx">noAck</span><span class="o">:</span> <span class="kc">true</span><span class="p">});</span> + <span class="p">});</span> +<span class="p">}</span> + +<span class="c1">//Random id generator</span> +<span class="kd">function</span> <span class="nx">randomid</span><span class="p">()</span> <span class="p">{</span> + <span class="k">return</span> <span class="k">new</span> <span class="nb">Date</span><span class="p">().</span><span class="nx">getTime</span><span class="p">().</span><span class="nx">toString</span><span class="p">()</span> <span class="o">+</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">random</span><span class="p">().</span><span class="nx">toString</span><span class="p">()</span> <span class="o">+</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">random</span><span class="p">().</span><span class="nx">toString</span><span class="p">();</span> +<span class="p">}</span> + +<span class="nx">app</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="s1">&#39;/upload&#39;</span><span class="p">,</span> <span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="kd">let</span> <span class="nx">img</span> <span class="o">=</span> <span class="nx">req</span><span class="p">.</span><span class="nx">files</span><span class="p">.</span><span class="nx">image</span><span class="p">;</span> + + <span class="kd">let</span> <span class="nx">id</span> <span class="o">=</span> <span class="nx">randomid</span><span class="p">();</span> + + <span class="c1">//Event listener that will fire when the proper randomid is provided</span> + <span class="nx">eventEmitter</span><span class="p">.</span><span class="nx">once</span><span class="p">(</span><span class="nx">id</span><span class="p">,</span> <span class="nx">msg</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="nx">res</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="nx">msg</span><span class="p">,</span> <span class="s1">&#39;binary&#39;</span><span class="p">);</span> + <span class="nx">res</span><span class="p">.</span><span class="nx">end</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="s1">&#39;binary&#39;</span><span class="p">);</span> + <span class="p">});</span> + + <span class="c1">//Checks if the queue exists, and create it if needed.</span> + <span class="nx">channel</span><span class="p">.</span><span class="nx">assertQueue</span><span class="p">(</span><span class="nx">QUEUE</span><span class="p">)</span> + <span class="c1">//Sent the buffered img to the queue with the ID and the responseQueue</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="nx">channel</span><span class="p">.</span><span class="nx">sendToQueue</span><span class="p">(</span><span class="nx">QUEUE</span><span class="p">,</span> <span class="nx">img</span><span class="p">.</span><span class="nx">data</span><span class="p">,</span> <span class="p">{</span><span class="nx">correlationId</span><span class="o">:</span><span class="nx">id</span><span class="p">,</span> <span class="nx">replyTo</span><span class="o">:</span> <span class="s1">&#39;amq.rabbitmq.reply-to&#39;</span><span class="p">}));</span> + +<span class="p">});</span> + +<span class="c1">//Finally start the app with the given port number</span> +<span class="c1">//now we initialize the rabbitmq connection before start the server</span> +<span class="nx">init</span><span class="p">()</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="nx">app</span><span class="p">.</span><span class="nx">listen</span><span class="p">(</span><span class="mi">4000</span><span class="p">,</span> <span class="p">()</span> <span class="p">=&gt;</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;Example app listening on port 4000!&#39;</span><span class="p">)))</span> + <span class="p">.</span><span class="k">catch</span><span class="p">(</span><span class="nx">err</span><span class="p">=&gt;</span><span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="nx">err</span><span class="p">));</span> +</pre></div> +<p>Ok, now we have our server code rewritten so let's see our worker code. Create a file named 'worker.js' and let's see how it's gonna be. It's really simple. You initialize a connection with RabbitMQ too, create a channel, check if the queue exists and start watching for incoming messages. When an image arrives, we do the job with it and send back to the &quot;replyTo&quot; queue the optimized image for the proper sender (correlationId). In the end, we do an acknowledge of the message so it get's out from the queue.</p> +<div class="highlight"><pre><span></span><span class="kr">const</span> <span class="nx">imagemin</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;imagemin&#39;</span><span class="p">);</span> +<span class="kr">const</span> <span class="nx">imageminPngquant</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;imagemin-pngquant&#39;</span><span class="p">);</span> + +<span class="kd">let</span> <span class="nx">channel</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span> +<span class="kr">const</span> <span class="nx">QUEUE</span> <span class="o">=</span> <span class="s1">&#39;imgqueue&#39;</span><span class="p">;</span> + +<span class="nx">require</span><span class="p">(</span><span class="s1">&#39;amqplib&#39;</span><span class="p">).</span><span class="nx">connect</span><span class="p">(</span><span class="s1">&#39;amqp://localhost&#39;</span><span class="p">)</span> +<span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">conn</span> <span class="p">=&gt;</span><span class="nx">conn</span><span class="p">.</span><span class="nx">createChannel</span><span class="p">())</span> +<span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">ch</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="nx">ch</span><span class="p">.</span><span class="nx">assertQueue</span><span class="p">(</span><span class="nx">QUEUE</span><span class="p">)</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="c1">//Watch incomming messages</span> + <span class="nx">ch</span><span class="p">.</span><span class="nx">consume</span><span class="p">(</span><span class="nx">QUEUE</span><span class="p">,</span> <span class="nx">msg</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="nx">imagemin</span><span class="p">.</span><span class="nx">buffer</span><span class="p">(</span><span class="nx">msg</span><span class="p">.</span><span class="nx">content</span><span class="p">,</span> <span class="p">{</span> + <span class="nx">plugins</span><span class="o">:</span> <span class="p">[</span><span class="nx">imageminPngquant</span><span class="p">()]</span> + <span class="p">})</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">out</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="c1">//Send back to the sender (replyTo) queue and give the correlationId back</span> + <span class="c1">//so we can emit the event.</span> + <span class="nx">ch</span><span class="p">.</span><span class="nx">sendToQueue</span><span class="p">(</span><span class="nx">msg</span><span class="p">.</span><span class="nx">properties</span><span class="p">.</span><span class="nx">replyTo</span><span class="p">,</span> <span class="nx">out</span><span class="p">,</span> <span class="p">{</span> + <span class="nx">correlationId</span><span class="o">:</span> <span class="nx">msg</span><span class="p">.</span><span class="nx">properties</span><span class="p">.</span><span class="nx">correlationId</span> + <span class="p">});</span> + + <span class="c1">//Acknowledge the job done with the message.</span> + <span class="nx">ch</span><span class="p">.</span><span class="nx">ack</span><span class="p">(</span><span class="nx">msg</span><span class="p">);</span> + <span class="p">});</span> + <span class="p">});</span> + <span class="p">});</span> +<span class="p">});</span> +</pre></div> +<p>The key points here are. Open just one connection to the hole server. You CAN create one channel for every request that you receive, but it can take some time if you have a really big cluster of RabbitMQ. It was a quick tutorial, but I hope that it was able to clear a few questions that you might have when working with rabbit and express.</p> +Microservices with NodeJS, Express.js and RabbitMQ Part 12018-04-04T11:25:00-03:002018-04-04T11:25:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-04-04:/microservices_nodejs_express_rabbitmq_part_1.html<p>This is the first part of a microservices development series. The service will consist of the bellow architecture, where we will expose an image optimizer service that will forward the request to a <a class="reference external" href="https://www.rabbitmq.com/">RabbitMQ</a> queue and answer with the bytecode of the optimized image. It shouldn't be a long series …</p><p>This is the first part of a microservices development series. The service will consist of the bellow architecture, where we will expose an image optimizer service that will forward the request to a <a class="reference external" href="https://www.rabbitmq.com/">RabbitMQ</a> queue and answer with the bytecode of the optimized image. It shouldn't be a long series so let's see what we can do.</p> +<img alt="Service architecture" src="/images/microservices_rabit_pt1.png" /> +<p>Let's get our environment working. First, we'll need to install the libraries that we'll use.</p> +<p>Create a dir and initialize the nodejs application inside it (<cite>npm init</cite>) and then let's install the deps.</p> +<ul class="simple"> +<li>amqplib - AMQP lib to interact with rabbitmq</li> +<li>express - Do our basic rest API</li> +<li>express-fileupload - easy file upload parser</li> +<li>imagemin and imagemin-pngquant - our image compacter</li> +</ul> +<div class="highlight"><pre><span></span>npm install --save express amqplib express-fileupload imagemin imagemin-pngquant +</pre></div> +<p>Now let's write the entry points for our service, we'll have two basic entry points. The path <cite>/</cite> that will have a welcome message, the second path will be <cite>/upload</cite> and this is the one that will handle the image and produce a job for our workers.</p> +<div class="highlight"><pre><span></span><span class="kr">const</span> <span class="nx">express</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;express&#39;</span><span class="p">);</span> +<span class="kr">const</span> <span class="nx">fileUpload</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;express-fileupload&#39;</span><span class="p">);</span> + +<span class="c1">//Instantiate the app and set the fileupload parser to manage files</span> +<span class="kr">const</span> <span class="nx">app</span> <span class="o">=</span> <span class="nx">express</span><span class="p">();</span> +<span class="nx">app</span><span class="p">.</span><span class="nx">use</span><span class="p">(</span><span class="nx">fileUpload</span><span class="p">());</span> + +<span class="c1">//Our index entry point</span> +<span class="nx">app</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;/&#39;</span><span class="p">,</span> <span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="nx">res</span><span class="p">.</span><span class="nx">send</span><span class="p">(</span><span class="s1">&#39;Hello From ImageCompacter service&#39;</span><span class="p">));</span> + +<span class="c1">//The path that will handle the image file and throw them to the queue</span> +<span class="nx">app</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="s1">&#39;/upload&#39;</span><span class="p">,</span> <span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="c1">//With express-fileupload we can grab the files like this</span> + <span class="kd">let</span> <span class="nx">img</span> <span class="o">=</span> <span class="nx">req</span><span class="p">.</span><span class="nx">files</span><span class="p">.</span><span class="nx">image</span><span class="p">;</span> <span class="c1">//&quot;image&quot; is the name of the input</span> + + <span class="nx">res</span><span class="p">.</span><span class="nx">send</span><span class="p">(</span><span class="s1">&#39;Not ready yet&#39;</span><span class="p">);</span> +<span class="p">});</span> + +<span class="c1">//Finally start the app with the given port number</span> +<span class="nx">app</span><span class="p">.</span><span class="nx">listen</span><span class="p">(</span><span class="mi">4000</span><span class="p">,</span> <span class="p">()</span> <span class="p">=&gt;</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;Example app listening on port 4000!&#39;</span><span class="p">));</span> +</pre></div> +<p>Let's check if it works, run the service with node.</p> +<div class="highlight"><pre><span></span>node index.js +Example app listening on port <span class="m">4000</span>! +</pre></div> +<p>Open the browser and check if it prints our hello message when accessing <cite>localhost:4000</cite>. Works? Greate. Now let's work with the image and see how we do it. To optimize our image, we'll use the library imagemin and <a class="reference external" href="https://www.npmjs.com/package/imagemin-pngquant">imagemin-pngquant</a>, it will be that simple for now, we'll work with rabbitmq latter.</p> +<div class="highlight"><pre><span></span><span class="kr">const</span> <span class="nx">imagemin</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;imagemin&#39;</span><span class="p">);</span> +<span class="kr">const</span> <span class="nx">imageminPngquant</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;imagemin-pngquant&#39;</span><span class="p">);</span> +<span class="c1">//...</span> + +<span class="c1">//The path that will handle the image file and throw them to the queue</span> +<span class="nx">app</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="s1">&#39;/upload&#39;</span><span class="p">,</span> <span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="kd">let</span> <span class="nx">img</span> <span class="o">=</span> <span class="nx">req</span><span class="p">.</span><span class="nx">files</span><span class="p">.</span><span class="nx">image</span><span class="p">;</span> <span class="c1">//&quot;image&quot; is the name of the input</span> + + <span class="nx">imagemin</span><span class="p">.</span><span class="nx">buffer</span><span class="p">(</span><span class="nx">img</span><span class="p">.</span><span class="nx">data</span><span class="p">,</span> <span class="p">{</span> + <span class="nx">plugins</span><span class="o">:</span> <span class="p">[</span><span class="nx">imageminPngquant</span><span class="p">()]</span> + <span class="p">})</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">out</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="nx">res</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="nx">out</span><span class="p">,</span><span class="s1">&#39;binary&#39;</span><span class="p">);</span> + <span class="nx">res</span><span class="p">.</span><span class="nx">end</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="s1">&#39;binary&#39;</span><span class="p">);</span> + <span class="p">});</span> +<span class="p">});</span> + + <span class="c1">//...</span> +</pre></div> +<p>Use <a class="reference external" href="https://www.getpostman.com/">Postman</a> to test the request. To see if it will work, make a request to <cite>http://localhost:4000/upload</cite> with a formdata with a file. Select the &quot;send and Download&quot; instead of &quot;Send&quot; and you should have an image after that. Bellow an image of how your postman should be.</p> +<img alt="Postman" src="/images/microservice_postman.png" /> +<p>That's it for today, next week we'll change our code to use RabbitMQ.</p> +Scaffolding a React app with Parcel and Yeoman2018-03-17T13:00:00-03:002018-03-17T13:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-03-17:/scaffolding_react_app_with_parcel_yeoman.html<p>Since <a class="reference external" href="https://parceljs.org/">Parcel JS</a> arrived, I've been using it a lot as an awesome alternative for WebPack. Webpack isn't bad but IMO it's too complex for the job and parcel do the same (at least the basic) with almost zero configuration. But if you need to create many apps (like a …</p><p>Since <a class="reference external" href="https://parceljs.org/">Parcel JS</a> arrived, I've been using it a lot as an awesome alternative for WebPack. Webpack isn't bad but IMO it's too complex for the job and parcel do the same (at least the basic) with almost zero configuration. But if you need to create many apps (like a react app) over and over again, it get's a lil boring following the basic steps.</p> +<div class="highlight"><pre><span></span>npm init -y +npm install --save react +npm install --save react-dom +npm install --save-dev parcel-bundler +npm install --save-dev babel-preset-env +npm install --save-dev babel-preset-react + +<span class="c1">#create .babelrc file</span> +<span class="c1">#create html, css, jsx files</span> + +parcel index.html +</pre></div> +<p>It's not a hard job, a simple shell script do the job, but what if you need some IFs when creating the app, or even change a few things at the <cite>package.json</cite>? A shell script still does the job, but come on... There is a better way. <a class="reference external" href="http://yeoman.io/">Yeoman</a> is here for you. I've already <a class="reference external" href="https://www.sipmann.com/desenvolvendo-app-firefoxos-pt.html">talked about it</a> on another post (Portuguese post).</p> +<p>Straight to the point, I've released a Yeoman generator to get the things a lil quicker. The name is <a class="reference external" href="https://www.npmjs.com/package/generator-parcel-react">generator-parcel-react</a> and it still lacks a few things that I will deal with soon. It's pretty simple to use it.</p> +<div class="highlight"><pre><span></span><span class="c1">#First time only</span> +npm install -g yo +npm install -g generator-parcel-react + +<span class="c1">#every time you create a new app</span> +yo parcel-react +</pre></div> +<p>And that's it. Right now you can scaffold and app with React, SASS and React Router. Hope you like it and feel free to ask new features.</p> + \ No newline at end of file diff --git a/feeds/front-end.atom.xml.gz b/feeds/front-end.atom.xml.gz new file mode 100644 index 000000000..71e5e8dcf Binary files /dev/null and b/feeds/front-end.atom.xml.gz differ diff --git a/feeds/java.atom.xml b/feeds/java.atom.xml new file mode 100644 index 000000000..4d3da8486 --- /dev/null +++ b/feeds/java.atom.xml @@ -0,0 +1,89 @@ + +Sipmann - Javahttps://www.sipmann.com/2018-03-09T12:35:00-03:00Could not open connection with MySQL and Hibernate2018-03-09T12:35:00-03:002018-03-09T12:35:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-03-09:/cloud-not-open-connection-java-mysql-hibernate.html<p>Last day I decided to deploy a MySQL Docker image to work with my Java application. I've been using PostgreSQL instead and have no problems at all, but after I moved to MySQL, the app didn't connect anymore with the database and throw some &quot;Could not open connection&quot; at my …</p><p>Last day I decided to deploy a MySQL Docker image to work with my Java application. I've been using PostgreSQL instead and have no problems at all, but after I moved to MySQL, the app didn't connect anymore with the database and throw some &quot;Could not open connection&quot; at my face, but why? I've tried to connect to it manually and got the same problem.</p> +<p>After some research, I found that the true error should be java.sql.SQLException: null, message from server: &quot;Host '172.17.0.4' is not allowed to connect to this MySQL server&quot; but it wasn't showing to me...</p> +<p>After all, be aware that with the docker image MySQL:5.7.21 (latest version right now) the root user isn't allowed to remote connect to the database (it's alright, security reasons) and if you still want to do remote connections to it with root there are a few things you can do.</p> +<ol class="arabic simple"> +<li>Create a user or allow root to access from other IPs.</li> +</ol> +<div class="highlight"><pre><span></span><span class="o">#</span><span class="k">No</span> <span class="k">access</span> <span class="k">to</span> <span class="k">user</span> <span class="n">root</span> <span class="k">on</span> <span class="k">any</span> <span class="n">other</span> <span class="n">IP</span> +<span class="k">SELECT</span> <span class="k">User</span><span class="p">,</span> <span class="k">Host</span> <span class="k">FROM</span> <span class="n">mysql</span><span class="p">.</span><span class="k">user</span><span class="p">;</span> +<span class="o">+</span><span class="c1">---------------+-----------+</span> +<span class="o">|</span> <span class="k">User</span> <span class="o">|</span> <span class="k">Host</span> <span class="o">|</span> +<span class="o">+</span><span class="c1">---------------+-----------+</span> +<span class="o">|</span> <span class="n">healthchecker</span> <span class="o">|</span> <span class="n">localhost</span> <span class="o">|</span> +<span class="o">|</span> <span class="n">root</span> <span class="o">|</span> <span class="n">localhost</span> <span class="o">|</span> +<span class="o">+</span><span class="c1">---------------+-----------+</span> +<span class="mi">2</span> <span class="k">rows</span> <span class="k">in</span> <span class="k">set</span> <span class="p">(</span><span class="mi">0</span><span class="p">.</span><span class="mi">01</span> <span class="n">sec</span><span class="p">)</span> + +<span class="k">CREATE</span> <span class="k">USER</span> <span class="s1">&#39;newuser&#39;</span><span class="o">@</span><span class="s1">&#39;%&#39;</span> <span class="n">IDENTIFIED</span> <span class="k">BY</span> <span class="s1">&#39;password&#39;</span><span class="p">;</span> <span class="o">#%</span> <span class="n">mean</span> <span class="k">any</span> <span class="n">IP</span> +<span class="k">GRANT</span> <span class="k">ALL</span> <span class="k">PRIVILEGES</span> <span class="k">ON</span> <span class="o">*</span><span class="p">.</span><span class="o">*</span> <span class="k">TO</span> <span class="s1">&#39;newuser&#39;</span><span class="o">@</span><span class="s1">&#39;%&#39;</span><span class="p">;</span> <span class="o">#*</span><span class="p">.</span><span class="o">*</span> <span class="n">mean</span> <span class="k">database</span><span class="p">.</span><span class="k">table</span> <span class="p">;)</span> +</pre></div> +<ol class="arabic simple" start="2"> +<li>Use MariaDB instead, witch come (at least on the version 10.2.13) with root allowed to do remote connections and will work like MySQL :)</li> +</ol> +<p>I changed to <a class="reference external" href="https://mariadb.org/">MariaDB</a> as it work without creating user or any changes on the Java code or the <cite>docker run command</cite>.</p> +Solving java.net.SocketException: Protocol family unavailable on a Java + Docker + WildFly2018-03-04T17:40:00-03:002018-03-04T17:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-03-04:/socketException-protocol-family-unavailable-java-docker-wildfly.html<p>On the last days I've been playing with <a class="reference external" href="http://wildfly-swarm.io/">WildFly Swarm</a> and I decided to deploy a simple app with Docker. Should work fine, at least that was what I thought. Built a container with the following Dockerfile and instead of a working web app, all that I got was the …</p><p>On the last days I've been playing with <a class="reference external" href="http://wildfly-swarm.io/">WildFly Swarm</a> and I decided to deploy a simple app with Docker. Should work fine, at least that was what I thought. Built a container with the following Dockerfile and instead of a working web app, all that I got was the error <cite>java.net.SocketException: Protocol family unavailable</cite>.</p> +<div class="highlight"><pre><span></span><span class="k">FROM</span> <span class="s">java:openjdk-8-jdk</span> + +<span class="k">COPY</span> target/issues.jar /opt/issues.jar + +<span class="k">EXPOSE</span><span class="s"> 8080</span> + +<span class="k">CMD</span> <span class="p">[</span><span class="s2">&quot;java&quot;</span><span class="p">,</span><span class="s2">&quot;-jar&quot;</span><span class="p">,</span><span class="s2">&quot;/opt/issues.jar&quot;</span><span class="p">]</span> +</pre></div> +<p>For some reason, WildFly and Java decided to use the IPv6 network interface from Docker instead the v4, so all you have to do is tell Java to prefer IPv4 instead with the following configuration option in your pom.xml file inside your WildFly plugin.</p> +<div class="highlight"><pre><span></span><span class="nt">&lt;plugin&gt;</span> + <span class="nt">&lt;groupId&gt;</span>org.wildfly.swarm<span class="nt">&lt;/groupId&gt;</span> + <span class="nt">&lt;artifactId&gt;</span>wildfly-swarm-plugin<span class="nt">&lt;/artifactId&gt;</span> + <span class="nt">&lt;version&gt;</span>2018.2.0<span class="nt">&lt;/version&gt;</span> + + <span class="c">&lt;!-- ADD THIS --&gt;</span> + <span class="nt">&lt;configuration&gt;</span> + <span class="nt">&lt;mainClass&gt;</span>org.wildfly.swarm.examples.netflix.ribbon.frontend.Main<span class="nt">&lt;/mainClass&gt;</span> + <span class="nt">&lt;properties&gt;</span> + <span class="nt">&lt;java.net.preferIPv4Stack&gt;</span>true<span class="nt">&lt;/java.net.preferIPv4Stack&gt;</span> + <span class="nt">&lt;/properties&gt;</span> + <span class="nt">&lt;/configuration&gt;</span> +</pre></div> +<p>Another way to solve is adding the same properties to the run command at the Dockerfile, so you choose where you'll add it. Bellow the Dockerfile solution.</p> +<div class="highlight"><pre><span></span><span class="k">FROM</span> <span class="s">java:openjdk-8-jdk</span> +<span class="k">ENV</span> <span class="nv">JAVA_OPTS</span><span class="o">=</span><span class="s2">&quot;-Djava.net.preferIPv4Stack=true -Djava.net.preferIPv4Addresses=true&quot;</span> + +<span class="k">COPY</span> target/issues.jar /opt/issues.jar + +<span class="k">EXPOSE</span><span class="s"> 8080</span> + +<span class="k">ENTRYPOINT</span> <span class="nb">exec</span> java <span class="nv">$JAVA_OPTS</span> -jar /opt/issues.jar +</pre></div> +Java - Files.readAllBytes throws OutOfMemory2018-02-17T13:00:00-02:002018-02-17T13:00:00-02:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-02-17:/reading-files-java-readAllBytes-outofmemory.html<p>When you need to interact with files, there's the possibility to read all bytes from the file with <cite>Files.readAllBytes</cite>. But be aware of the kinds of files your application will deal with because the Java API files have a limit for the buffer that is defined as <cite>Integer.MAX_VALUE …</cite></p><p>When you need to interact with files, there's the possibility to read all bytes from the file with <cite>Files.readAllBytes</cite>. But be aware of the kinds of files your application will deal with because the Java API files have a limit for the buffer that is defined as <cite>Integer.MAX_VALUE</cite> as you can see above or at the OpenJDK sources.</p> +<div class="highlight"><pre><span></span><span class="kd">public</span> <span class="kd">static</span> <span class="kt">byte</span><span class="o">[]</span> <span class="nf">readAllBytes</span><span class="p">(</span><span class="n">Path</span> <span class="n">path</span><span class="p">)</span> <span class="kd">throws</span> <span class="n">IOException</span> <span class="p">{</span> + <span class="k">try</span> <span class="p">(</span><span class="n">FileChannel</span> <span class="n">fc</span> <span class="o">=</span> <span class="n">FileChannel</span><span class="p">.</span><span class="na">open</span><span class="p">(</span><span class="n">path</span><span class="p">))</span> <span class="p">{</span> + <span class="kt">long</span> <span class="n">size</span> <span class="o">=</span> <span class="n">fc</span><span class="p">.</span><span class="na">size</span><span class="p">();</span> + <span class="k">if</span> <span class="p">(</span><span class="n">size</span> <span class="o">&gt;</span> <span class="p">(</span><span class="kt">long</span><span class="p">)</span><span class="n">Integer</span><span class="p">.</span><span class="na">MAX_VALUE</span><span class="p">)</span> + <span class="k">throw</span> <span class="k">new</span> <span class="n">OutOfMemoryError</span><span class="p">(</span><span class="s">&quot;Required array size too large&quot;</span><span class="p">);</span> + + <span class="kt">byte</span><span class="o">[]</span> <span class="n">arr</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">byte</span><span class="o">[</span><span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">size</span><span class="o">]</span><span class="p">;</span> + <span class="n">ByteBuffer</span> <span class="n">bb</span> <span class="o">=</span> <span class="n">ByteBuffer</span><span class="p">.</span><span class="na">wrap</span><span class="p">(</span><span class="n">arr</span><span class="p">);</span> + <span class="k">while</span> <span class="p">(</span><span class="n">bb</span><span class="p">.</span><span class="na">hasRemaining</span><span class="p">())</span> <span class="p">{</span> + <span class="k">if</span> <span class="p">(</span><span class="n">fc</span><span class="p">.</span><span class="na">read</span><span class="p">(</span><span class="n">bb</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> + <span class="c1">// truncated</span> + <span class="k">break</span><span class="p">;</span> + <span class="p">}</span> + <span class="p">}</span> + + <span class="kt">int</span> <span class="n">nread</span> <span class="o">=</span> <span class="n">bb</span><span class="p">.</span><span class="na">position</span><span class="p">();</span> + <span class="k">return</span> <span class="p">(</span><span class="n">nread</span> <span class="o">==</span> <span class="n">size</span><span class="p">)</span> <span class="o">?</span> <span class="n">arr</span> <span class="p">:</span> <span class="n">Arrays</span><span class="p">.</span><span class="na">copyOf</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="n">nread</span><span class="p">);</span> + <span class="p">}</span> +<span class="p">}</span> +</pre></div> +<p>With that in mind, check if isn't better read chunks of bytes e work with that slice in exchange of loading the whole file into the memory ;). Above a simple example of how you can read chunks of bytes from the file.</p> +<div class="highlight"><pre><span></span><span class="kt">byte</span><span class="o">[]</span> <span class="n">buffer</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">byte</span><span class="o">[</span><span class="mi">1024</span><span class="o">]</span><span class="p">;</span> +<span class="n">FileInputStream</span> <span class="n">in</span> <span class="o">=</span> <span class="k">new</span> <span class="n">FileInputStream</span><span class="p">(</span><span class="n">file</span><span class="p">);</span> +<span class="kt">int</span> <span class="n">rc</span> <span class="o">=</span> <span class="n">in</span><span class="p">.</span><span class="na">read</span><span class="p">(</span><span class="n">buffer</span><span class="p">);</span> +<span class="k">while</span> <span class="p">(</span><span class="n">rc</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span> +<span class="p">{</span> + <span class="c1">//crazy stuff here with buffer</span> + <span class="n">rc</span> <span class="o">=</span> <span class="n">in</span><span class="p">.</span><span class="na">read</span><span class="p">(</span><span class="n">buffer</span><span class="p">);</span> +<span class="p">}</span> +</pre></div> + \ No newline at end of file diff --git a/feeds/java.atom.xml.gz b/feeds/java.atom.xml.gz new file mode 100644 index 000000000..2b3dbe289 Binary files /dev/null and b/feeds/java.atom.xml.gz differ diff --git a/feeds/linux.atom.xml b/feeds/linux.atom.xml new file mode 100644 index 000000000..592393ad9 --- /dev/null +++ b/feeds/linux.atom.xml @@ -0,0 +1,92 @@ + +Sipmann - Linuxhttps://www.sipmann.com/2020-10-20T19:00:00-03:00Zabbix Running on Low Memory Mode2020-10-20T19:00:00-03:002020-10-20T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-20:/zabbix-running-on-low-memory-mode.html<p>Hey folks, another Zabbix post today. This one it's about increasing the Zabbix Server Cache. It's pretty common (if you have the default settings only) get a warning about your <code>Zabbix value cache running on low memory mode</code> at your dashboard or logs.</p> +<p><img alt="Zabbix Dashboard warning about the memory problem" src="/images/zabbix_low_memory_mode.png"> +<img alt="Zabbix Dashboard cache graph 70% used" src="/images/zabbix_cache_filling.png"></p> +<p>To solve, go back to your Zabbix …</p><p>Hey folks, another Zabbix post today. This one it's about increasing the Zabbix Server Cache. It's pretty common (if you have the default settings only) get a warning about your <code>Zabbix value cache running on low memory mode</code> at your dashboard or logs.</p> +<p><img alt="Zabbix Dashboard warning about the memory problem" src="/images/zabbix_low_memory_mode.png"> +<img alt="Zabbix Dashboard cache graph 70% used" src="/images/zabbix_cache_filling.png"></p> +<p>To solve, go back to your Zabbix config file (<code>zabbix_server.conf</code>) and look for the tag <em>CacheSize</em>. Uncomment it and set to a value bigger than 8M (8M it's the default value). In my case, we set a cache of 100M. After the change, restart the service.</p> +<div class="highlight"><pre><span></span><code><span class="c1">### Option: CacheSize</span> +<span class="c1"># Size of configuration cache, in bytes.</span> +<span class="c1"># Shared memory size for storing host, item and trigger data.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 128K-64G</span> +<span class="c1"># Default:</span> +<span class="na">CacheSize</span><span class="o">=</span><span class="s">100M #uncomment this line</span> +</code></pre></div> + +<p><img alt="Zabbix Dashboard resolved memory problem" src="/images/zabbix_low_memory_solved.png"></p> +<p>See ya folks.</p>Zabbix poller processes more than 75%2020-07-02T19:00:00-03:002020-07-02T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-07-02:/zabbix-poller-processes-more-than-75.html<p>Hey folks, this is the third post about tweaking the Zabbix configurations. All changes that I've suggested here were based on a Zabbix Server with 50+ hosts. Another thing that can happen to your server, it's the poller get overwhelmed by the amount of servers that need to be polled …</p><p>Hey folks, this is the third post about tweaking the Zabbix configurations. All changes that I've suggested here were based on a Zabbix Server with 50+ hosts. Another thing that can happen to your server, it's the poller get overwhelmed by the amount of servers that need to be polled plus the ones that are not responding. Bellow two images where you can see the log and the graphic where you can see the usage percent. </p> +<p><img alt="Dashboard log about the poller processes" src="/images/zabbix_pooler.png"></p> +<p><img alt="Graph showing the utilization percent of each collector" src="/images/zabbix_pooler_3.png"></p> +<p>To solve, let's go back to the <code>zabbix_server.conf</code> file and find two variables, <code>StartPollers</code> and <code>StartPollersUnreachable</code>. Increase them as needed. There's no magic number, you must see what works for you. But keep in mind that the <code>StartPollersUnreachable</code> is responsible for that host that can't be "reached" (of course) and will hold your poller more time.</p> +<div class="highlight"><pre><span></span><code><span class="c1">### Option: StartPollers</span> +<span class="c1"># Number of pre-forked instances of pollers.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 0-1000</span> +<span class="c1"># Default:</span> +<span class="na">StartPollers</span><span class="o">=</span><span class="s">20</span> + +<span class="c1">#...</span> + +<span class="c1">### Option: StartPollersUnreachable</span> +<span class="c1"># Number of pre-forked instances of pollers for unreachable hosts (including IPMI and Java).</span> +<span class="c1"># At least one poller for unreachable hosts must be running if regular, IPMI or Java pollers</span> +<span class="c1"># are started.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 0-1000</span> +<span class="c1"># Default:</span> +<span class="na">StartPollersUnreachable</span><span class="o">=</span><span class="s">5</span> +</code></pre></div> + +<p>After the change, restart the server and wait a few moments and take a look again at your dashboard. Bellow the effect that I've got.</p> +<p><img alt="Graph showing the new utilization percent of the processes after the changes" src="/images/zabbix_pooler_4.png"></p>Zabbix ICMP pinger processes more than 75%2020-05-25T16:00:00-03:002020-05-25T16:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-05-25:/zabbix-icmp-pinger-processes-more-than-75.html<p>So your monitoring sytems have grown and your zabbix started loggin "Zabbix icmp pinger processes more than 75% busy" at the dashboard.</p> +<p><img alt="Dashboard do zabbix avisando sobre o erro" src="/images/zabbix_pinger01.png"></p> +<p>All you have to do is open your config file (<code>/etc/zabbix/zabbix_server.conf</code>) and find the a tag named <code>StartPingers</code>. It'll be commented by default. Uncomment it …</p><p>So your monitoring sytems have grown and your zabbix started loggin "Zabbix icmp pinger processes more than 75% busy" at the dashboard.</p> +<p><img alt="Dashboard do zabbix avisando sobre o erro" src="/images/zabbix_pinger01.png"></p> +<p>All you have to do is open your config file (<code>/etc/zabbix/zabbix_server.conf</code>) and find the a tag named <code>StartPingers</code>. It'll be commented by default. Uncomment it and set it's value to something like 3 or 4. It should solve your problem.</p> +<div class="highlight"><pre><span></span><code><span class="c1">### Option: StartPingers</span> +<span class="c1"># Number of pre-forked instances of ICMP pingers.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 0-1000</span> +<span class="c1"># Default:</span> +<span class="nv">StartPingers</span><span class="o">=</span><span class="m">4</span> +</code></pre></div> + +<h2>How many Pingers do I need?</h2> +<p>Well, there is no exact answer to this. If you set it too high, you'll be wasting resources. The best way to solve, it's increasing them as soon as you notice the percentage growing.</p>Zabbix Server Out of Memory2020-02-27T19:00:00-03:002020-02-27T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-02-27:/zabbix-server-out-of-memory-crash.html<p>Do you have a crashing Zabbix Server and looking through the log <code>/var/log/zabbix/zabbix_server.log</code> you see the following out of memory message?</p> +<div class="highlight"><pre><span></span><code>__mem_malloc: skipped <span class="m">0</span> asked <span class="m">24</span> skip_min <span class="m">18446744073709551615</span> skip_max <span class="m">0</span> +<span class="o">[</span>file:dbconfig.c,line:94<span class="o">]</span> __zbx_mem_realloc<span class="o">()</span>: out of memory <span class="o">(</span>requested <span class="m">16</span> bytes<span class="o">)</span> +<span class="o">[</span>file:dbconfig.c,line …</code></pre></div><p>Do you have a crashing Zabbix Server and looking through the log <code>/var/log/zabbix/zabbix_server.log</code> you see the following out of memory message?</p> +<div class="highlight"><pre><span></span><code>__mem_malloc: skipped <span class="m">0</span> asked <span class="m">24</span> skip_min <span class="m">18446744073709551615</span> skip_max <span class="m">0</span> +<span class="o">[</span>file:dbconfig.c,line:94<span class="o">]</span> __zbx_mem_realloc<span class="o">()</span>: out of memory <span class="o">(</span>requested <span class="m">16</span> bytes<span class="o">)</span> +<span class="o">[</span>file:dbconfig.c,line:94<span class="o">]</span> __zbx_mem_realloc<span class="o">()</span>: please increase CacheSize configuration parameter +</code></pre></div> + +<p>Besides the clear solution to the error, that's a common issue on servers that have a few monitoring items on it (servers, switches, firewalls, databases, etc...). To solve, go to your zabbix_server.conf and look for the CacheSize property and set it to a higher value. Its default should be 8M. At a customer that has somewhere between 4 servers, 7 firewalls/appliances, and a few other things, a 32M did the job, but you can set up to 8G.</p> +<p>See ya folks.</p>Connecting to a database through SSH2018-03-29T10:03:00-03:002018-03-29T10:03:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-03-29:/connecting_to_database_through_ssh.html<p>If someday, for some reason, you need to establish a connection with a database which is behind a firewall and you only have SSH access on that server (and you don't want to use a CLI) you can do an SSH tunnel. It's pretty simple, bellow has a sample of …</p><p>If someday, for some reason, you need to establish a connection with a database which is behind a firewall and you only have SSH access on that server (and you don't want to use a CLI) you can do an SSH tunnel. It's pretty simple, bellow has a sample of how to allow connections to a remote Firebird database.</p> +<div class="highlight"><pre><span></span>ssh -L <span class="m">3051</span>:192.168.1.9:3050 username@192.168.1.9 +</pre></div> +<p>The <cite>-L</cite> parameter tells to SSH do a local port forwarding on local port <cite>3051</cite> to remote port <cite>3050</cite>. You can use it to a connection with many services, not just databases.</p> +<p>You can do the reverse kind of tunnel, forward connections from the host to your local machine, you just have to change the parameter form &quot;-L&quot; to &quot;-R&quot; and the port order is inverted, first come the port where the server will listen and after your localhost port. This remote port forwarding must be enabled on the server. Look for <cite>GatewayPorts</cite> at the ssh config file.</p> +<div class="highlight"><pre><span></span>ssh -R <span class="m">3050</span>:localhost:3050 username@192.168.1.9 +</pre></div> +<p>Why whould you need something like that?? Let's say you want to share a localhost site/database with a friend, but your internet connection don't allow you to expose any port but you have access to a remote server witch can do that. Problem solved ;).</p> +Change display settings on linux with Disper2018-02-27T12:40:00-03:002018-02-27T12:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-02-27:/linux-external-display-with-disper.html<p>From time to time, I change the Linux distro on my laptop or just do a fresh install on it. And once in a while, have random problems with external displays. It can be something really &quot;simple&quot; like don't detecting the external monitor or something crazy like the image below …</p><p>From time to time, I change the Linux distro on my laptop or just do a fresh install on it. And once in a while, have random problems with external displays. It can be something really &quot;simple&quot; like don't detecting the external monitor or something crazy like the image below.</p> +<img alt="Display bug" src="/images/bug.png" /> +<p>As you can see at the image, the mint detected the display but mirrored it in a crazy way that works but doesn't at the same time. If you try anything and doesn't get working, or just wanna skip the whole job of configuring complexes text files, give a try to <a class="reference external" href="http://willem.engen.nl/projects/disper/">Disper</a>. Download the latest version. +Extract it on any folder, and make install it (on the extracted folder).</p> +<div class="highlight"><pre><span></span>make install +</pre></div> +<p>After that, you can start using it... There are a few options that will serve you well.</p> +<div class="highlight"><pre><span></span>disper -e <span class="c1">#extend your display</span> +</pre></div> +<div class="highlight"><pre><span></span>disper -c <span class="c1">#clone your display</span> +</pre></div> +<div class="highlight"><pre><span></span>disper -s <span class="c1">#only your external display</span> +</pre></div> + \ No newline at end of file diff --git a/feeds/linux.atom.xml.gz b/feeds/linux.atom.xml.gz new file mode 100644 index 000000000..c4e7261c1 Binary files /dev/null and b/feeds/linux.atom.xml.gz differ diff --git a/feeds/mauricio-camargo-sipmann.atom.xml b/feeds/mauricio-camargo-sipmann.atom.xml new file mode 100644 index 000000000..6b5c0f27e --- /dev/null +++ b/feeds/mauricio-camargo-sipmann.atom.xml @@ -0,0 +1,813 @@ + +Sipmann - Maurício Camargo Sipmannhttps://www.sipmann.com/2020-12-21T13:30:00-03:00Monitoring MySQL restarts with PowerShell2020-12-21T13:30:00-03:002020-12-21T13:30:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-12-21:/monitoring-mysql-restarts-with-powershell.html<p>Hey folks, it's time for another PowerShell script. If you haven't seen the other ones, check the links below.</p> +<ul> +<li><a href="https://www.sipmann.com/en/monitoring-mysql-replication-with-powershell.html">Monitoring MySQL replication with PowerShell</a></li> +</ul> +<p>Well, this one it's a pretty simple script, but again, if your customer doesn't have a Zabbix server or doesn't allow you to setup one to …</p><p>Hey folks, it's time for another PowerShell script. If you haven't seen the other ones, check the links below.</p> +<ul> +<li><a href="https://www.sipmann.com/en/monitoring-mysql-replication-with-powershell.html">Monitoring MySQL replication with PowerShell</a></li> +</ul> +<p>Well, this one it's a pretty simple script, but again, if your customer doesn't have a Zabbix server or doesn't allow you to setup one to do the monitoring, a set of scripts can be handy. We start executing some basic query <code>SHOW GLOBAL STATUS LIKE 'Uptime'</code>, with that we'll get exactly what we're looking for.</p> +<p>If for some reason, the command fails (watch for the "global" variable called <code>$lastExitCode</code>), we send an e-mail telling you about that connection problem.</p> +<p>And then, we get to the part where we parse the value, this one is pretty similar to the parse we did on the first post about using PowerShell to monitor MySQL. But we basically look for the Value line, split it by space and then parse the second position to an integer. And then all we have to do is check if the uptime is lower than our threshold, if it is we send an e-mail.</p> +<div class="highlight"><pre><span></span><code><span class="nv">$MailFrom</span> <span class="p">=</span> <span class="s1">&#39;maurio[at]sipmann.com&#39;</span> +<span class="nv">$MailTo</span> <span class="p">=</span> <span class="s1">&#39;mauricio[at]sipmann.com&#39;</span> +<span class="nv">$MysqlHost</span> <span class="p">=</span> <span class="s1">&#39;127.0.0.1&#39;</span> +<span class="nv">$MysqlUser</span> <span class="p">=</span> <span class="s1">&#39;root&#39;</span> +<span class="nv">$MysqlPass</span> <span class="p">=</span> <span class="s1">&#39;123&#39;</span> + + +<span class="nv">$data</span> <span class="p">=</span> <span class="p">$(</span><span class="n">mysql</span> <span class="n">-h</span> <span class="nv">$MysqlHost</span> <span class="n">-u</span> <span class="nv">$MysqlUser</span> <span class="n">-p</span><span class="s2">&quot;$MysqlPass&quot;</span> <span class="n">-e</span> <span class="s2">&quot;SHOW GLOBAL STATUS LIKE &#39;Uptime&#39; \G&quot;</span><span class="p">)</span> + +<span class="cm">&lt;# Unable to execute the sql Command #&gt;</span> +<span class="k">if</span> <span class="p">(</span><span class="nv">$lastExitCode</span> <span class="o">-eq</span> <span class="n">1</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Send-MailMessage</span> <span class="n">-To</span> <span class="nv">$MailTo</span> <span class="n">-From</span> <span class="nv">$MailFrom</span> <span class="n">-Subject</span> <span class="s1">&#39;Connection problem&#39;</span> <span class="n">-bodyAsHtml</span> <span class="s2">&quot;Connection problem on host ${MysqlHost}&quot;</span> <span class="n">-Credential</span> <span class="nb">Get-Credential</span> <span class="n">-SmtpServer</span> <span class="s1">&#39;smtp.office365.com&#39;</span> <span class="n">-Port</span> <span class="n">587</span> <span class="n">-UseSsl</span> + <span class="n">exit</span> +<span class="p">}</span> + +<span class="nv">$UpTime</span> <span class="p">=</span> <span class="no">[int]</span><span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Value:&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> + +<span class="cm">&lt;# If the uptime is lower then 20 minutes #&gt;</span> +<span class="k">if</span> <span class="p">(</span><span class="nv">$UpTime</span> <span class="o">-lt</span> <span class="n">1200</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Send-MailMessage</span> <span class="n">-To</span> <span class="nv">$MailTo</span> <span class="n">-From</span> <span class="nv">$MailFrom</span> <span class="n">-Subject</span> <span class="s2">&quot;MySQL Restarted&quot;</span> <span class="n">-bodyAsHtml</span> <span class="s2">&quot;MySQL host ${MysqlHost} restarted less than 20 minutes ago&quot;</span> <span class="n">-Credential</span> <span class="nb">Get-Credential</span> <span class="n">-SmtpServer</span> <span class="s1">&#39;smtp.office365.com&#39;</span> <span class="n">-Port</span> <span class="n">587</span> <span class="n">-UseSsl</span> +<span class="p">}</span> +</code></pre></div> + +<p>This script (and the other ones I use) is available at my GitHub <a href="https://github.com/sipmann/PowerShellScripts">here</a>. Keep in mind that the ones on the GitHub repo, are a little different from here.</p>Changing a MySQL user password across multiple application instances without downtime2020-12-09T13:40:00-03:002020-12-09T13:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-12-09:/mysql-dual-password-functionality.html<p>Do you need to change the password of a MySQL user that it's being used in an application, and can't allow a single downtime? Well, MySQL 8.0.14 came with a feature called <a href="https://dev.mysql.com/doc/refman/8.0/en/password-management.html#dual-passwords">Dual Password Support</a>, with it you can change the password keeping the previous password as a …</p><p>Do you need to change the password of a MySQL user that it's being used in an application, and can't allow a single downtime? Well, MySQL 8.0.14 came with a feature called <a href="https://dev.mysql.com/doc/refman/8.0/en/password-management.html#dual-passwords">Dual Password Support</a>, with it you can change the password keeping the previous password as a kind of backup. That way you still can log in using the old password or can start using the new one. With that, the password change workflow it's the following.</p> +<p>1) Change password keeping the old one;</p> +<p>2) Deploy the new config to your app/cluster;</p> +<p>3) Discard the old password.</p> +<p>To change the password and keep the old one, you have the following command.</p> +<div class="highlight"><pre><span></span><code><span class="k">ALTER</span> <span class="n">USER</span> <span class="s1">&#39;appuser&#39;</span><span class="o">@</span><span class="s1">&#39;localhost&#39;</span> <span class="n">IDENTIFIED</span> <span class="k">BY</span> <span class="s1">&#39;new_password&#39;</span> <span class="n">RETAIN</span> <span class="n">CURRENT</span> <span class="n">PASSWORD</span><span class="p">;</span> +</code></pre></div> + +<p>To discard the old one, run the following.</p> +<div class="highlight"><pre><span></span><code><span class="k">ALTER</span> <span class="n">USER</span> <span class="s1">&#39;appuser&#39;</span><span class="o">@</span><span class="s1">&#39;localhost&#39;</span> <span class="n">DISCARD</span> <span class="n">OLD</span> <span class="n">PASSWORD</span><span class="p">;</span> +</code></pre></div> + +<p>And you are done. Hope you find it as useful as I :)</p>Apache Nifi JSON to SQL Replacing underscore2020-12-02T14:00:00-03:002020-12-02T14:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-12-02:/apache-nifi-json-to-sql-replacing-underscore.html<p>Recently I was doing some ETL with Apache NiFi. But after a few minutes of drawing my flow, I saw that the component ConvertJSONToSQL was replacing the underscore ('_') from the field name in the where condition (I was preparing an Update SQL). That was weird because, at the set …</p><p>Recently I was doing some ETL with Apache NiFi. But after a few minutes of drawing my flow, I saw that the component ConvertJSONToSQL was replacing the underscore ('_') from the field name in the where condition (I was preparing an Update SQL). That was weird because, at the set statement, the field name was kept intact. After some research, I found that the property (see bellow) <code>Translate Field Names</code> was responsible for that weird replacement.</p> +<p><img alt="Apache NiFi JSONToSQL config" src="/images/apache_nifi_jsontosql.png"></p> +<p>Before setting it to <strong>FALSE</strong>, be aware that the properties on your JSON data must match exactly the name of your fields.</p>Blocking a user on SQL Server based on a schedule2020-11-14T07:00:00-03:002020-11-14T07:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-11-14:/blocking-user-on-sql-server-based-on-schedule.html<p>Ok, some time ago, I've posted about how you can set limits to connections on SQL Server using the <a href="https://www.sipmann.com/limiting-connection-resources-sql-server.html#.X6Cz8IhKhPY">Resource Governor</a>. But what if you can't use it? You always can block logins using a login trigger, but I don't like the idea of having selects running on every login …</p><p>Ok, some time ago, I've posted about how you can set limits to connections on SQL Server using the <a href="https://www.sipmann.com/limiting-connection-resources-sql-server.html#.X6Cz8IhKhPY">Resource Governor</a>. But what if you can't use it? You always can block logins using a login trigger, but I don't like the idea of having selects running on every login. So I came across with a solution using a stored procedure, a table and the Agent.</p> +<p>The main idea is, store the time that a user must be blocked and using the Agent, disable or enable the user. Bellow you can see the table (the table is in Portuguese, but I have a few comment blocks to help you).</p> +<div class="highlight"><pre><span></span><code><span class="k">CREATE</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"> </span><span class="p">(</span><span class="w"></span> +<span class="w"> </span><span class="n">Id</span><span class="w"> </span><span class="nc">INT</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">LoginName</span><span class="w"> </span><span class="nc">NVARCHAR</span><span class="p">(</span><span class="mi">100</span><span class="p">)</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">HrInicio</span><span class="w"> </span><span class="nc">TIME</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"> </span><span class="cm">/* Startint block time */</span><span class="w"></span> +<span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="nc">TIME</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"> </span><span class="cm">/* Ending block time */</span><span class="w"></span> +<span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="nc">INT</span><span class="w"> </span><span class="k">DEFAULT</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="cm">/* 0 = unblocked, 1 = blocked */</span><span class="w"></span> +<span class="w"> </span><span class="k">PRIMARY</span><span class="w"> </span><span class="k">KEY</span><span class="w"> </span><span class="p">(</span><span class="n">Id</span><span class="p">)</span><span class="w"></span> +<span class="p">);</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> + +<span class="cm">/* Don&#39;t block the SA user, precautions, you know */</span><span class="w"></span> +<span class="k">ALTER</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"></span> +<span class="w"> </span><span class="k">ADD</span><span class="w"> </span><span class="k">CONSTRAINT</span><span class="w"> </span><span class="n">chk_users</span><span class="w"> </span><span class="k">CHECK</span><span class="w"> </span><span class="p">(</span><span class="n">LoginName</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;sa&#39;</span><span class="p">));</span><span class="w"></span> + +<span class="k">ALTER</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"></span> +<span class="w"> </span><span class="k">ADD</span><span class="w"> </span><span class="k">CONSTRAINT</span><span class="w"> </span><span class="n">chk_hora_final_maior</span><span class="w"> </span><span class="k">CHECK</span><span class="w"> </span><span class="p">(</span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="n">HrInicio</span><span class="p">);</span><span class="w"></span> + +<span class="k">ALTER</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"></span> +<span class="w"> </span><span class="k">ADD</span><span class="w"> </span><span class="k">CONSTRAINT</span><span class="w"> </span><span class="n">chk_status_bloqueio</span><span class="w"> </span><span class="k">CHECK</span><span class="w"> </span><span class="p">(</span><span class="n">Bloqueado</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">));</span><span class="w"></span> + +<span class="k">CREATE</span><span class="w"> </span><span class="k">SEQUENCE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">seq_HorariosBloqueio</span><span class="w"> </span><span class="k">START</span><span class="w"> </span><span class="k">WITH</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="n">INCREMENT</span><span class="w"> </span><span class="k">BY</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +</code></pre></div> + +<p>After creating the table, let's check the procedure that will handle the enabling/disabling the users. Be aware that on the procedure, I've set the database name where the table was stored, you can change it replacing the <code>DBATOOLS</code> text to the database name where you created the table.</p> +<div class="highlight"><pre><span></span><code><span class="k">IF</span><span class="w"> </span><span class="nf">OBJECT_ID</span><span class="p">(</span><span class="s1">&#39;dbo.sp_ValidarLogin&#39;</span><span class="p">)</span><span class="w"> </span><span class="k">IS</span><span class="w"> </span><span class="k">NULL</span><span class="w"></span> +<span class="w"> </span><span class="k">EXEC</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;CREATE PROCEDURE dbo.sp_ValidarLogin AS RETURN 0;&#39;</span><span class="p">);</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> + +<span class="k">CREATE</span><span class="w"> </span><span class="ow">OR</span><span class="w"> </span><span class="k">ALTER</span><span class="w"> </span><span class="k">PROC</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">sp_ValidarLogin</span><span class="w"></span> +<span class="k">AS</span><span class="w"> </span><span class="k">BEGIN</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="nc">NVARCHAR</span><span class="p">(</span><span class="mi">100</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="nc">TIME</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="k">SET</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nf">CAST</span><span class="p">(</span><span class="nf">GETDATE</span><span class="p">()</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="nc">TIME</span><span class="p">);</span><span class="w"></span> + +<span class="w"> </span><span class="cm">/* Block the ones that aren&#39;t blocked already and maches the time */</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="n">block_cursor</span><span class="w"> </span><span class="nc">CURSOR</span><span class="w"></span> +<span class="w"> </span><span class="k">FOR</span><span class="w"> </span><span class="k">SELECT</span><span class="w"> </span><span class="n">LoginName</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&lt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&gt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"></span> +<span class="w"> </span><span class="k">OPEN</span><span class="w"> </span><span class="n">block_cursor</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">block_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> + +<span class="w"> </span><span class="k">WHILE</span><span class="w"> </span><span class="nb">@@FETCH_STATUS</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"></span> +<span class="w"> </span><span class="k">BEGIN</span><span class="w"></span> +<span class="w"> </span><span class="k">exec</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;ALTER LOGIN &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="s1">&#39; DISABLE;&#39;</span><span class="p">);</span><span class="w"></span> + +<span class="w"> </span><span class="k">print</span><span class="w"> </span><span class="s1">&#39;Bloqued usuario &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">block_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> +<span class="w"> </span><span class="k">END</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">CLOSE</span><span class="w"> </span><span class="n">block_cursor</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="k">DEALLOCATE</span><span class="w"> </span><span class="n">block_cursor</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">UPDATE</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">SET</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&lt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&gt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"></span> + + +<span class="w"> </span><span class="cm">/* Enable up who was blocked */</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="nc">CURSOR</span><span class="w"></span> +<span class="w"> </span><span class="k">FOR</span><span class="w"> </span><span class="k">SELECT</span><span class="w"> </span><span class="n">LoginName</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="p">(</span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">OR</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="p">)</span><span class="w"></span> +<span class="w"> </span><span class="k">OPEN</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> + +<span class="w"> </span><span class="k">WHILE</span><span class="w"> </span><span class="nb">@@FETCH_STATUS</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"></span> +<span class="w"> </span><span class="k">BEGIN</span><span class="w"></span> +<span class="w"> </span><span class="k">exec</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;ALTER LOGIN &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"> </span><span class="o">+</span><span class="s1">&#39; ENABLE;&#39;</span><span class="p">);</span><span class="w"></span> + +<span class="w"> </span><span class="k">print</span><span class="w"> </span><span class="s1">&#39;Unbloqued usuario &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> +<span class="w"> </span><span class="k">END</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">CLOSE</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="k">DEALLOCATE</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">UPDATE</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">SET</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="p">(</span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">OR</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="p">)</span><span class="w"></span> +<span class="k">END</span><span class="p">;</span><span class="w"></span> +</code></pre></div> + +<p>Ok, so now all you have to do, is schedule a job to run that stored procedure from minute to minute. Again, the main idea is tell the procedure when a user must be blocked and when it'll be unblocked. </p> +<div class="highlight"><pre><span></span><code><span class="err"> -- Will block the user protheus from 10 AM till 15 PM</span> +<span class="err"> INSERT INTO dbo.HorariosBloqueio (Id, LoginName, HrInicio, HrTermino) VALUES (NEXT VALUE FOR seq_HorariosBloqueio, &#39;protheus&#39;, &#39;10:00:00&#39;, &#39;15:00:00&#39;);</span> +</code></pre></div>How to set columns on select using Entity Framework2020-10-28T19:00:00-03:002020-10-28T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-28:/select_specific_fields_with_efcore.html<p>So, you use Entity Framework Core, and you usually code your selects like the following, maybe you are getting too much data.</p> +<div class="highlight"><pre><span></span><code><span class="kt">var</span> <span class="n">products</span> <span class="p">=</span> <span class="n">Products</span> + <span class="p">.</span><span class="n">Where</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span> <span class="p">&gt;</span> <span class="m">0</span><span class="p">)</span> + <span class="p">.</span><span class="n">OrderBy</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">)</span> + <span class="p">.</span><span class="n">ToList</span><span class="p">()</span> +</code></pre></div> + +<p>Running the query above, on my table, you'll get the following output, take a look …</p><p>So, you use Entity Framework Core, and you usually code your selects like the following, maybe you are getting too much data.</p> +<div class="highlight"><pre><span></span><code><span class="kt">var</span> <span class="n">products</span> <span class="p">=</span> <span class="n">Products</span> + <span class="p">.</span><span class="n">Where</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span> <span class="p">&gt;</span> <span class="m">0</span><span class="p">)</span> + <span class="p">.</span><span class="n">OrderBy</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">)</span> + <span class="p">.</span><span class="n">ToList</span><span class="p">()</span> +</code></pre></div> + +<p>Running the query above, on my table, you'll get the following output, take a look at how many columns you are getting back from your database.</p> +<p><img alt="Screenshot with every single column" src="/images/ef_core_allcolumns.png"></p> +<p>In my case, I only care about the Title, PublishedData, and a small description. So to get back only these fields, we have a few options. In the first one, we'll set the fields and return them as a dynamic object, the second one, is to give the .NET a class to use. </p> +<div class="highlight"><pre><span></span><code><span class="kt">var</span> <span class="n">products</span> <span class="p">=</span> <span class="n">Products</span> + + <span class="p">.</span><span class="n">Select</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="k">new</span> <span class="p">{</span><span class="n">p</span><span class="p">.</span><span class="n">ProductID</span><span class="p">,</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">,</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span><span class="p">,</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitPrice</span><span class="p">})</span> + <span class="c1">//.Select(p =&gt; new ProductDTO {p.ProductID, p.ProductName, p.UnitsInStock, p.UnitPrice})</span> + + <span class="p">.</span><span class="n">Where</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span> <span class="p">&gt;</span> <span class="m">0</span><span class="p">)</span> + <span class="p">.</span><span class="n">OrderBy</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">)</span> + <span class="p">.</span><span class="n">ToList</span><span class="p">()</span> +</code></pre></div> + +<p><img alt="Screenshot with fewer columns and also fewer data size" src="/images/ef_core_less_columns.png"></p>Zabbix Running on Low Memory Mode2020-10-20T19:00:00-03:002020-10-20T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-20:/zabbix-running-on-low-memory-mode.html<p>Hey folks, another Zabbix post today. This one it's about increasing the Zabbix Server Cache. It's pretty common (if you have the default settings only) get a warning about your <code>Zabbix value cache running on low memory mode</code> at your dashboard or logs.</p> +<p><img alt="Zabbix Dashboard warning about the memory problem" src="/images/zabbix_low_memory_mode.png"> +<img alt="Zabbix Dashboard cache graph 70% used" src="/images/zabbix_cache_filling.png"></p> +<p>To solve, go back to your Zabbix …</p><p>Hey folks, another Zabbix post today. This one it's about increasing the Zabbix Server Cache. It's pretty common (if you have the default settings only) get a warning about your <code>Zabbix value cache running on low memory mode</code> at your dashboard or logs.</p> +<p><img alt="Zabbix Dashboard warning about the memory problem" src="/images/zabbix_low_memory_mode.png"> +<img alt="Zabbix Dashboard cache graph 70% used" src="/images/zabbix_cache_filling.png"></p> +<p>To solve, go back to your Zabbix config file (<code>zabbix_server.conf</code>) and look for the tag <em>CacheSize</em>. Uncomment it and set to a value bigger than 8M (8M it's the default value). In my case, we set a cache of 100M. After the change, restart the service.</p> +<div class="highlight"><pre><span></span><code><span class="c1">### Option: CacheSize</span> +<span class="c1"># Size of configuration cache, in bytes.</span> +<span class="c1"># Shared memory size for storing host, item and trigger data.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 128K-64G</span> +<span class="c1"># Default:</span> +<span class="na">CacheSize</span><span class="o">=</span><span class="s">100M #uncomment this line</span> +</code></pre></div> + +<p><img alt="Zabbix Dashboard resolved memory problem" src="/images/zabbix_low_memory_solved.png"></p> +<p>See ya folks.</p>Monitoring MySQL Replication Status with PowerShell2020-10-14T19:00:00-03:002020-10-14T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-14:/monitoring-mysql-replication-with-powershell.html<p>I've been migration some bash scripts that I have to PowerShell, and it's time to migrate a script that monitors the replication of a MySQL database. The credit for the original script goes to <a href="https://handyman.dulare.com/mysql-replication-status-alerts-with-bash-script/">Paweł</a>. It's a simple script where I seek a few tags/fields that we get from …</p><p>I've been migration some bash scripts that I have to PowerShell, and it's time to migrate a script that monitors the replication of a MySQL database. The credit for the original script goes to <a href="https://handyman.dulare.com/mysql-replication-status-alerts-with-bash-script/">Paweł</a>. It's a simple script where I seek a few tags/fields that we get from <code>SHOW SLAVE STATUS\G</code> command, the fields are. <code>Slave_IO_Running</code>, <code>Slave_SQL_Running</code>, and <code>Seconds_Behind_Master</code>. I still need to figure out the proper way to store/read variables like usernames and passwords, if you have any tips, feel free to even make a pull request (<a href="https://github.com/sipmann/PowerShellScripts">here</a>) at the git where I'll store some scripts.</p> +<div class="highlight"><pre><span></span><code><span class="cm">&lt;#</span> +<span class="cm"> Variables definition</span> +<span class="cm">#&gt;</span> +<span class="nv">$MaxSeconds</span> <span class="p">=</span> <span class="n">120</span> <span class="c"># Max seconds behind master allowed</span> +<span class="nv">$MysqlUser</span> <span class="p">=</span> <span class="s1">&#39;root&#39;</span> +<span class="nv">$MysqlPass</span> <span class="p">=</span> <span class="s1">&#39;&#39;</span> + +<span class="nv">$MailTo</span> <span class="p">=</span> <span class="s1">&#39;mauricio@sipmann.com&#39;</span> +<span class="nv">$MailFrom</span> <span class="p">=</span> <span class="s1">&#39;mauricio@sipmann.com&#39;</span> + + +<span class="nv">$data</span> <span class="p">=</span> <span class="p">$(</span><span class="n">mysql</span> <span class="n">-u</span> <span class="nv">$MysqlUser</span> <span class="n">-p</span><span class="s2">&quot;$MysqlPass&quot;</span> <span class="n">-e</span> <span class="s1">&#39;SHOW SLAVE STATUS \G&#39;</span><span class="p">)</span> + +<span class="c">#Debug data</span> +<span class="c">#$data = Get-Content &#39;c:\temp\sampleresult.txt&#39;</span> + +<span class="cm">&lt;# Parse the data #&gt;</span> +<span class="nv">$IORunning</span> <span class="p">=</span> <span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Slave_IO_Running:&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> +<span class="nv">$SQLRunning</span> <span class="p">=</span> <span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Slave_SQL_Running:&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> +<span class="nv">$LastErrNo</span> <span class="p">=</span> <span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Last_Errno&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> +<span class="nv">$SecondsBh</span> <span class="p">=</span> <span class="no">[int]</span><span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Seconds_Behind_Master&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> + +<span class="k">If</span> <span class="p">(</span><span class="nv">$IORunning</span> <span class="o">-Eq</span> <span class="s1">&#39;No&#39;</span> <span class="o">-Or</span> <span class="nv">$SQLRunning</span> <span class="o">-Eq</span> <span class="s1">&#39;No&#39;</span> <span class="o">-Or</span> <span class="nv">$SecondsBh</span> <span class="o">-gt</span> <span class="nv">$MaxSeconds</span><span class="p">)</span> <span class="p">{</span> + <span class="nv">$MailBody</span> <span class="p">=</span> <span class="s1">&#39;&lt;h1&gt;Problema na replicação&lt;/h1&gt;&lt;br&gt;&#39;</span> + + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39; IO Running: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$IORunning</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39; SQL Running: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$SQLRunning</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39;Seconds Behind: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$SecondsBh</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39; Last Err No: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$LastErrNo</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + + <span class="cm">&lt;# Send e-mail, maybe some telegram message here too #&gt;</span> + <span class="nb">Send-MailMessage</span> <span class="n">-To</span> <span class="nv">$MailTo</span> <span class="n">-From</span> <span class="nv">$MailFrom</span> <span class="n">-Subject</span> <span class="s1">&#39;Problemas na replicação&#39;</span> <span class="n">-bodyAsHtml</span> <span class="nv">$MailBody</span> <span class="n">-Credential</span> <span class="p">(</span><span class="nb">Get-Credential</span><span class="p">)</span> <span class="n">-SmtpServer</span> <span class="s1">&#39;smtp.office365.com&#39;</span> <span class="n">-Port</span> <span class="n">587</span> <span class="n">-UseSsl</span> +<span class="p">}</span> <span class="k">Else</span> <span class="p">{</span> + <span class="nb">Write-Host</span> <span class="s2">&quot;Up and running&quot;</span> +<span class="p">}</span> +</code></pre></div>Microsoft Against Covid2020-10-03T19:00:00-03:002020-10-03T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-03:/microsoft-against-covid.html<p>Has your job been affected by covid? Well, last week I've posted on <a href="https://grepora.com/2020/09/17/microsoft-ignite-certification-voucher/">Grepora</a> about a Free Certification Voucher that Microsoft was giving away at the Microsoft Ignite event. After that, I found that they were also giving a huge discount to people who have had their job affected by …</p><p>Has your job been affected by covid? Well, last week I've posted on <a href="https://grepora.com/2020/09/17/microsoft-ignite-certification-voucher/">Grepora</a> about a Free Certification Voucher that Microsoft was giving away at the Microsoft Ignite event. After that, I found that they were also giving a huge discount to people who have had their job affected by covid pandemic. </p> +<p>To see more details about if you were eligible, access <a href="https://docs.microsoft.com/en-us/learn/certifications/skillingoffer">https://docs.microsoft.com/en-us/learn/certifications/skillingoffer</a>.</p>The power of PowerShell2020-09-21T19:00:00-03:002020-09-21T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-09-21:/the-power-of-powershell.html<p>As a long time Linux user, I've automated a few things with bash scripts and stayed away from PowerShell... I've moved to a Windows environment a few years ago and still, haven gave a shot to PS. But why not? I've made a few scripts to automate some tasks at …</p><p>As a long time Linux user, I've automated a few things with bash scripts and stayed away from PowerShell... I've moved to a Windows environment a few years ago and still, haven gave a shot to PS. But why not? I've made a few scripts to automate some tasks at a Protheus server.</p> +<p>I found the PS scripts being easy to read and understand. Bellow, we have a script to remove files filtering their extension (or no extension at all like the following script). </p> +<div class="highlight"><pre><span></span><code><span class="nb">Get-ChildItem</span> <span class="s2">&quot;C:\TOTVS\protheus_data\system&quot;</span> <span class="o">-File</span> <span class="n">-Filter</span> <span class="p">*.</span> <span class="p">|</span> <span class="nb">Move-Item</span> <span class="n">-Force</span> <span class="n">-Destination</span> <span class="p">{</span> + <span class="cm">&lt;# Diretory where the files will be moved. You can use Date formats to help name it #&gt;</span> + <span class="cm">&lt;# LastWriteTime proprtie from the current file #&gt;</span> + <span class="nv">$dir</span> <span class="p">=</span> <span class="s2">&quot;C:\bad_files\{0:yyyy\\MM\\dd}&quot;</span> <span class="o">-f</span> <span class="nv">$_</span><span class="p">.</span><span class="n">LastWriteTime</span> + <span class="nv">$null</span> <span class="p">=</span> <span class="n">mkdir</span> <span class="nv">$dir</span> <span class="n">-Force</span> + <span class="s2">&quot;$dir\</span><span class="p">$(</span><span class="nv">$_</span><span class="p">.</span><span class="n">Name</span><span class="p">)</span><span class="s2">&quot;</span> +<span class="p">}</span> +</code></pre></div> + +<p>Have you ever been in the need to remove files based on other file content? Bello a script where I read a file that has the names of files that I want to remove. </p> +<div class="highlight"><pre><span></span><code><span class="k">foreach</span><span class="p">(</span><span class="nv">$line</span> <span class="k">in</span> <span class="nb">Get-Content</span> <span class="p">.\</span><span class="n">Desktop</span><span class="p">\</span><span class="n">bad_files</span><span class="p">.</span><span class="n">txt</span><span class="p">)</span> <span class="p">{</span> + <span class="k">if</span> <span class="p">(</span><span class="nb">Test-Path</span><span class="p">(</span><span class="s1">&#39;\\x.y.z.a\c$\TOTVS\protheus_data\xmls\&#39;</span><span class="p">+</span><span class="nv">$line</span><span class="p">+</span><span class="s1">&#39;.xml&#39;</span><span class="p">))</span> <span class="p">{</span> + <span class="nb">Remove-Item</span><span class="p">(</span><span class="s1">&#39;\\x.y.z.a\c$\TOTVS\protheus_data\xmls\&#39;</span><span class="p">+</span><span class="nv">$line</span><span class="p">+</span><span class="s1">&#39;.xml&#39;</span><span class="p">)</span> + <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> + <span class="nb">echo </span><span class="nv">$line</span> <span class="p">+</span> <span class="s1">&#39; - File not found&#39;</span> + <span class="p">}</span> +<span class="p">}</span> +</code></pre></div> + +<p>And a bonus script to stop/start services (if you handle some Protheus Server, you know why I do that).</p> +<div class="highlight"><pre><span></span><code><span class="nv">$servicesNames</span> <span class="p">=</span> <span class="s1">&#39;app_main&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker1&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker2&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker3&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker4&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker5&#39;</span> + +<span class="nb">Write-host</span> <span class="s2">&quot;Stoping Services&quot;</span> +<span class="nb">Write-host</span> <span class="s2">&quot;--------------------------&quot;</span> + +<span class="k">foreach</span> <span class="p">(</span><span class="nv">$srv</span> <span class="k">in</span> <span class="nv">$servicesNames</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Write-host</span> <span class="s2">&quot;Stopping: &quot;</span> <span class="p">+</span> <span class="nv">$srv</span> + <span class="nv">$SrvPID</span> <span class="p">=</span> <span class="p">(</span><span class="nb">get-wmiobject</span> <span class="n">win32_service</span> <span class="p">|</span> <span class="nb">where </span><span class="p">{</span> <span class="nv">$_</span><span class="p">.</span><span class="n">name</span> <span class="o">-eq</span> <span class="nv">$srv</span><span class="p">}).</span><span class="n">processID</span> + <span class="nb">Write-host</span> <span class="s2">&quot;PID: &quot;</span> <span class="p">+</span> <span class="nv">$SrvPID</span> + + <span class="cm">&lt;# Force if the proccess is stucked #&gt;</span> + <span class="nb">Stop-Process</span> <span class="nv">$SrvPID</span> <span class="n">-Force</span> + <span class="nb">Write-host</span> <span class="s2">&quot;PDI &quot;</span> <span class="p">+</span> <span class="nv">$SrvPID</span> <span class="p">+</span> <span class="s2">&quot; stopped&quot;</span> +<span class="p">}</span> + + +<span class="nb">Write-host</span> <span class="s2">&quot;Starting Services&quot;</span> +<span class="nb">Write-host</span> <span class="s2">&quot;--------------------------&quot;</span> + +<span class="k">foreach</span> <span class="p">(</span><span class="nv">$srv</span> <span class="k">in</span> <span class="nv">$servicesNames</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Write-host</span> <span class="s2">&quot;Starting: &quot;</span> <span class="p">+</span> <span class="nv">$srv</span> + <span class="nb">Start-Service</span> <span class="nv">$srv</span> +<span class="p">}</span> +</code></pre></div> + +<p>Do you have any automated script? Share with us :)</p>Top Level Statement in C# 92020-07-29T19:00:00-03:002020-07-29T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-07-29:/top_level_statement_csharp_9.html<p>Hey folks, I'm coming along to tell you a few things about the new feature of C# 9. Every time you want to start a new project, you always have the same Main File, with the same structure. At the next version of C# (version 9), we'll have a new …</p><p>Hey folks, I'm coming along to tell you a few things about the new feature of C# 9. Every time you want to start a new project, you always have the same Main File, with the same structure. At the next version of C# (version 9), we'll have a new feature called <code>Top Level Statement</code>. With that, we'll be able to code our app without any namespace/class/public void static main structure. Take a look at the code below.</p> +<div class="highlight"><pre><span></span><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span> + +<span class="n">Console</span><span class="p">.</span><span class="n">WriteLine</span><span class="p">(</span><span class="s">&quot;Hello World!&quot;</span><span class="p">);</span> +</code></pre></div> + +<p>It looks pretty simple, but with this, you can play around with your code, and even code a simple/tiny Web API. To start playing with the new features, firstly download the <a href="https://dotnet.microsoft.com/download/dotnet/5.0">.net 5 SDK</a> and change your <code>.csproj</code> file to target the .net 5 and language preview like bellow.</p> +<div class="highlight"><pre><span></span><code><span class="nt">&lt;Project</span> <span class="na">Sdk=</span><span class="s">&quot;Microsoft.NET.Sdk&quot;</span><span class="nt">&gt;</span> + <span class="nt">&lt;PropertyGroup&gt;</span> + <span class="nt">&lt;OutputType&gt;</span>Exe<span class="nt">&lt;/OutputType&gt;</span> + <span class="nt">&lt;TargetFramework&gt;</span>net5.0<span class="nt">&lt;/TargetFramework&gt;</span> + <span class="nt">&lt;LangVersion&gt;</span>preview<span class="nt">&lt;/LangVersion&gt;</span> + <span class="nt">&lt;/PropertyGroup&gt;</span> +<span class="nt">&lt;/Project&gt;</span> +</code></pre></div> + +<p>And you're ready to play with the awesome features available in the preview. Let's code a way to get the image of the day from NASA API and print the Picture of the Day. No awesome code here, it's really a way to show how simple a simple call could be. After here, why not save the image in a file? Maybe send the file over telegram?</p> +<div class="highlight"><pre><span></span><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Net.Http</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Text.Json</span><span class="p">;</span> + +<span class="kt">var</span> <span class="n">API</span> <span class="p">=</span> <span class="s">&quot;https://api.nasa.gov/planetary/apod?hd=true&amp;api_key=DEMO_KEY&quot;</span><span class="p">;</span> +<span class="kt">var</span> <span class="n">cli</span> <span class="p">=</span> <span class="k">new</span> <span class="n">HttpClient</span><span class="p">();</span> + +<span class="kt">var</span> <span class="n">response</span> <span class="p">=</span> <span class="k">await</span> <span class="n">cli</span><span class="p">.</span><span class="n">GetAsync</span><span class="p">(</span><span class="n">API</span><span class="p">);</span> +<span class="kt">var</span> <span class="n">data</span> <span class="p">=</span> <span class="n">JsonSerializer</span><span class="p">.</span><span class="n">Deserialize</span><span class="p">&lt;</span><span class="n">NasaApi</span><span class="p">&gt;(</span><span class="k">await</span> <span class="n">response</span><span class="p">.</span><span class="n">Content</span><span class="p">.</span><span class="n">ReadAsStringAsync</span><span class="p">());</span> + +<span class="n">Console</span><span class="p">.</span><span class="n">WriteLine</span><span class="p">(</span><span class="n">data</span><span class="p">.</span><span class="n">Url</span><span class="p">);</span> +</code></pre></div> + +<p>That's it for today folks. Keep an eye open for the awesome features C# 9 will bring to us, there's plenty more features already available.</p>Zabbix poller processes more than 75%2020-07-02T19:00:00-03:002020-07-02T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-07-02:/zabbix-poller-processes-more-than-75.html<p>Hey folks, this is the third post about tweaking the Zabbix configurations. All changes that I've suggested here were based on a Zabbix Server with 50+ hosts. Another thing that can happen to your server, it's the poller get overwhelmed by the amount of servers that need to be polled …</p><p>Hey folks, this is the third post about tweaking the Zabbix configurations. All changes that I've suggested here were based on a Zabbix Server with 50+ hosts. Another thing that can happen to your server, it's the poller get overwhelmed by the amount of servers that need to be polled plus the ones that are not responding. Bellow two images where you can see the log and the graphic where you can see the usage percent. </p> +<p><img alt="Dashboard log about the poller processes" src="/images/zabbix_pooler.png"></p> +<p><img alt="Graph showing the utilization percent of each collector" src="/images/zabbix_pooler_3.png"></p> +<p>To solve, let's go back to the <code>zabbix_server.conf</code> file and find two variables, <code>StartPollers</code> and <code>StartPollersUnreachable</code>. Increase them as needed. There's no magic number, you must see what works for you. But keep in mind that the <code>StartPollersUnreachable</code> is responsible for that host that can't be "reached" (of course) and will hold your poller more time.</p> +<div class="highlight"><pre><span></span><code><span class="c1">### Option: StartPollers</span> +<span class="c1"># Number of pre-forked instances of pollers.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 0-1000</span> +<span class="c1"># Default:</span> +<span class="na">StartPollers</span><span class="o">=</span><span class="s">20</span> + +<span class="c1">#...</span> + +<span class="c1">### Option: StartPollersUnreachable</span> +<span class="c1"># Number of pre-forked instances of pollers for unreachable hosts (including IPMI and Java).</span> +<span class="c1"># At least one poller for unreachable hosts must be running if regular, IPMI or Java pollers</span> +<span class="c1"># are started.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 0-1000</span> +<span class="c1"># Default:</span> +<span class="na">StartPollersUnreachable</span><span class="o">=</span><span class="s">5</span> +</code></pre></div> + +<p>After the change, restart the server and wait a few moments and take a look again at your dashboard. Bellow the effect that I've got.</p> +<p><img alt="Graph showing the new utilization percent of the processes after the changes" src="/images/zabbix_pooler_4.png"></p>Monitoring a Website heath with Azure Functions2020-06-22T19:00:00-03:002020-06-22T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-06-22:/monitoring-website-heath-with-azure-functions.html<p>Sometimes you get your self in need to monitor a website's health or it's content for changes. Of course, there's plenty of options out there, but for the sake of curiosity, let's code our own to see what we can do. First things first. Everything you'll see here, you can …</p><p>Sometimes you get your self in need to monitor a website's health or it's content for changes. Of course, there's plenty of options out there, but for the sake of curiosity, let's code our own to see what we can do. First things first. Everything you'll see here, you can achieve with the <a href="https://azure.microsoft.com/free/">free tier</a> of azure.</p> +<p>The main idea of our app will be to monitor website health (status code). To create a new Azure Function Project, follow the steps below.</p> +<p><img alt="Steps to create a azure function project" src="/images/azure_functions.gif"></p> +<p>After creating the project, you'll have a few files. Open your main file and start coding. The main file will have a function called <code>Run</code> and you can code your request method. I've created an <code>async</code> method to make the request and log the output at the console. The full code you can see below.</p> +<div class="highlight"><pre><span></span><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Linq</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Net.Http</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Threading.Tasks</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">Microsoft.Azure.WebJobs</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">Microsoft.Azure.WebJobs.Host</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">Microsoft.Extensions.Logging</span><span class="p">;</span> + +<span class="k">namespace</span> <span class="nn">Sipmann.CheckMySite</span> +<span class="p">{</span> + <span class="k">public</span> <span class="k">static</span> <span class="k">class</span> <span class="nc">HttpCheck</span> + <span class="p">{</span> + + <span class="k">private</span> <span class="k">static</span> <span class="k">async</span> <span class="n">Task</span> <span class="nf">GetTask</span><span class="p">(</span><span class="kt">string</span> <span class="n">url</span><span class="p">,</span> <span class="n">ILogger</span> <span class="n">log</span><span class="p">)</span> + <span class="p">{</span> + <span class="kt">var</span> <span class="n">request</span> <span class="p">=</span> <span class="k">new</span> <span class="n">HttpRequestMessage</span><span class="p">(</span><span class="n">HttpMethod</span><span class="p">.</span><span class="n">Get</span><span class="p">,</span> <span class="n">url</span><span class="p">);</span> + + <span class="kt">var</span> <span class="n">client</span> <span class="p">=</span> <span class="k">new</span> <span class="n">HttpClient</span><span class="p">();</span> + <span class="kt">var</span> <span class="n">response</span> <span class="p">=</span> <span class="k">await</span> <span class="n">client</span><span class="p">.</span><span class="n">SendAsync</span><span class="p">(</span><span class="n">request</span><span class="p">);</span> + + <span class="k">if</span> <span class="p">(</span><span class="n">response</span><span class="p">.</span><span class="n">IsSuccessStatusCode</span><span class="p">)</span> + <span class="p">{</span> + <span class="n">log</span><span class="p">.</span><span class="n">LogInformation</span><span class="p">(</span><span class="err">$</span><span class="s">&quot;URL ${url} esta OK&quot;</span><span class="p">);</span> + <span class="p">}</span> + <span class="k">else</span> + <span class="p">{</span> + <span class="n">log</span><span class="p">.</span><span class="n">LogInformation</span><span class="p">(</span><span class="err">$</span><span class="s">&quot;URL ${url} não esta OK&quot;</span><span class="p">);</span> + <span class="p">}</span> + <span class="p">}</span> + +<span class="na"> [FunctionName(&quot;HttpCheck&quot;)]</span> + <span class="k">public</span> <span class="k">static</span> <span class="k">void</span> <span class="nf">Run</span><span class="p">([</span><span class="n">TimerTrigger</span><span class="p">(</span><span class="s">&quot;0 */5 * * * *&quot;</span><span class="p">)]</span><span class="n">TimerInfo</span> <span class="n">myTimer</span><span class="p">,</span> <span class="n">ILogger</span> <span class="n">log</span><span class="p">)</span> + <span class="p">{</span> + <span class="kt">var</span> <span class="n">urls</span> <span class="p">=</span> <span class="k">new</span><span class="p">[]{</span><span class="s">&quot;https://www.sipmann.com&quot;</span><span class="p">,</span> <span class="s">&quot;https://www.canezecanez.com.br&quot;</span><span class="p">};</span> + + <span class="c1">// Start every request and wait for them all to complete</span> + <span class="n">Task</span><span class="p">.</span><span class="n">WaitAll</span><span class="p">(</span><span class="n">urls</span><span class="p">.</span><span class="n">Select</span><span class="p">(</span><span class="n">url</span> <span class="p">=&gt;</span> <span class="n">GetTask</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">log</span><span class="p">)).</span><span class="n">ToArray</span><span class="p">());</span> + <span class="n">log</span><span class="p">.</span><span class="n">LogInformation</span><span class="p">(</span><span class="err">$</span><span class="s">&quot;Finalizou a fila&quot;</span><span class="p">);</span> + <span class="p">}</span> + <span class="p">}</span> +<span class="p">}</span> +</code></pre></div> + +<p>Now you can enhance the function and maybe send some alerts like a Telegram message when one of your sites went down.</p>Azure Data Fundamentals certification with 80% discount2020-06-09T12:30:00-03:002020-06-09T12:30:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-06-09:/azure-data-fundamentals-certification-80-discount.html<p>Hey folks, if you want to achieve some certification this year, keep an eye open for vouchers. A few months ago, Oracle released a set of free courses with certifications. Now it's Microsoft time. Microsoft is updating they're certifications and we have a voucher of 80% discount using the coupon …</p><p>Hey folks, if you want to achieve some certification this year, keep an eye open for vouchers. A few months ago, Oracle released a set of free courses with certifications. Now it's Microsoft time. Microsoft is updating they're certifications and we have a voucher of 80% discount using the coupon <strong>DP900Norfolk</strong> at the checkout of the beta certification DP-900. </p> +<p>Be aware that this certification is in beta and the result won't be instantly available as the regular ones. Access the following link and schedule your exam. <a href="https://docs.microsoft.com/pt-br/learn/certifications/exams/dp-900" target="_blank">https://docs.microsoft.com/pt-br/learn/certifications/exams/dp-900</a>.</p> +<p><strong>Update:</strong> There is a 80% voucher also for <a href="https://docs.microsoft.com/en-us/learn/certifications/azure-ai-fundamentals" target="_blank">https://docs.microsoft.com/en-us/learn/certifications/azure-ai-fundamentals</a>. Voucher: <strong>AI900Saratoga</strong></p>Zabbix ICMP pinger processes more than 75%2020-05-25T16:00:00-03:002020-05-25T16:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-05-25:/zabbix-icmp-pinger-processes-more-than-75.html<p>So your monitoring sytems have grown and your zabbix started loggin "Zabbix icmp pinger processes more than 75% busy" at the dashboard.</p> +<p><img alt="Dashboard do zabbix avisando sobre o erro" src="/images/zabbix_pinger01.png"></p> +<p>All you have to do is open your config file (<code>/etc/zabbix/zabbix_server.conf</code>) and find the a tag named <code>StartPingers</code>. It'll be commented by default. Uncomment it …</p><p>So your monitoring sytems have grown and your zabbix started loggin "Zabbix icmp pinger processes more than 75% busy" at the dashboard.</p> +<p><img alt="Dashboard do zabbix avisando sobre o erro" src="/images/zabbix_pinger01.png"></p> +<p>All you have to do is open your config file (<code>/etc/zabbix/zabbix_server.conf</code>) and find the a tag named <code>StartPingers</code>. It'll be commented by default. Uncomment it and set it's value to something like 3 or 4. It should solve your problem.</p> +<div class="highlight"><pre><span></span><code><span class="c1">### Option: StartPingers</span> +<span class="c1"># Number of pre-forked instances of ICMP pingers.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 0-1000</span> +<span class="c1"># Default:</span> +<span class="nv">StartPingers</span><span class="o">=</span><span class="m">4</span> +</code></pre></div> + +<h2>How many Pingers do I need?</h2> +<p>Well, there is no exact answer to this. If you set it too high, you'll be wasting resources. The best way to solve, it's increasing them as soon as you notice the percentage growing.</p>Zabbix Server Out of Memory2020-02-27T19:00:00-03:002020-02-27T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-02-27:/zabbix-server-out-of-memory-crash.html<p>Do you have a crashing Zabbix Server and looking through the log <code>/var/log/zabbix/zabbix_server.log</code> you see the following out of memory message?</p> +<div class="highlight"><pre><span></span><code>__mem_malloc: skipped <span class="m">0</span> asked <span class="m">24</span> skip_min <span class="m">18446744073709551615</span> skip_max <span class="m">0</span> +<span class="o">[</span>file:dbconfig.c,line:94<span class="o">]</span> __zbx_mem_realloc<span class="o">()</span>: out of memory <span class="o">(</span>requested <span class="m">16</span> bytes<span class="o">)</span> +<span class="o">[</span>file:dbconfig.c,line …</code></pre></div><p>Do you have a crashing Zabbix Server and looking through the log <code>/var/log/zabbix/zabbix_server.log</code> you see the following out of memory message?</p> +<div class="highlight"><pre><span></span><code>__mem_malloc: skipped <span class="m">0</span> asked <span class="m">24</span> skip_min <span class="m">18446744073709551615</span> skip_max <span class="m">0</span> +<span class="o">[</span>file:dbconfig.c,line:94<span class="o">]</span> __zbx_mem_realloc<span class="o">()</span>: out of memory <span class="o">(</span>requested <span class="m">16</span> bytes<span class="o">)</span> +<span class="o">[</span>file:dbconfig.c,line:94<span class="o">]</span> __zbx_mem_realloc<span class="o">()</span>: please increase CacheSize configuration parameter +</code></pre></div> + +<p>Besides the clear solution to the error, that's a common issue on servers that have a few monitoring items on it (servers, switches, firewalls, databases, etc...). To solve, go to your zabbix_server.conf and look for the CacheSize property and set it to a higher value. Its default should be 8M. At a customer that has somewhere between 4 servers, 7 firewalls/appliances, and a few other things, a 32M did the job, but you can set up to 8G.</p> +<p>See ya folks.</p>Flutter + firebase auth crashing2019-10-03T19:00:00-03:002019-10-03T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2019-10-03:/flutter_with_firebase_auth_crashing.html<p>Hey Folks, recently I've started learning <a href="https://flutter.dev/">Flutter</a> and right after a TODO List, I tried a Firebase integration. But as soon as I started setting the dependencies, my app stopped opening... just a crash. After a few logs digging, I've found the following log.</p> +<div class="highlight"><pre><span></span><code>AndroidRuntime: FATAL EXCEPTION: main +AndroidRuntime: Process …</code></pre></div><p>Hey Folks, recently I've started learning <a href="https://flutter.dev/">Flutter</a> and right after a TODO List, I tried a Firebase integration. But as soon as I started setting the dependencies, my app stopped opening... just a crash. After a few logs digging, I've found the following log.</p> +<div class="highlight"><pre><span></span><code>AndroidRuntime: FATAL EXCEPTION: main +AndroidRuntime: Process: com.example.diadocasal, PID: <span class="m">13672</span> +AndroidRuntime: java.lang.NoClassDefFoundError: Failed resolution of: Landroid/support/v4/util/ArrayMap<span class="p">;</span> +AndroidRuntime: at com.google.android.gms.internal.measurement.zzca.&lt;clinit&gt;<span class="o">(</span>Unknown Source:60<span class="o">)</span> +AndroidRuntime: at com.google.android.gms.internal.measurement.zzcm.zzr<span class="o">(</span>Unknown Source:7<span class="o">)</span> +AndroidRuntime: at com.google.android.gms.measurement.internal.zzfj.&lt;init&gt;<span class="o">(</span>Unknown Source:23<span class="o">)</span> +</code></pre></div> + +<p>Notice the "NoClassDefFound" of an ArrayMap. To solve that I did the following changes to the files:</p> +<div class="highlight"><pre><span></span><code><span class="c1">//build.gradle file</span> + <span class="n">ext</span><span class="p">.</span><span class="na">kotlin_version</span> <span class="o">=</span> <span class="err">&#39;</span><span class="mf">1.3.20</span><span class="err">&#39;</span> +<span class="o">[</span><span class="p">...</span><span class="o">]</span> + <span class="n">dependencies</span> <span class="p">{</span> + <span class="n">classpath</span> <span class="err">&#39;</span><span class="n">com</span><span class="p">.</span><span class="na">android</span><span class="p">.</span><span class="na">tools</span><span class="p">.</span><span class="na">build</span><span class="p">:</span><span class="n">gradle</span><span class="p">:</span><span class="mf">3.3.0</span><span class="err">&#39;</span> <span class="c1">// gradle version</span> +</code></pre></div> + +<div class="highlight"><pre><span></span><code><span class="c1">;gradle.properties file</span> +<span class="na">org.gradle.jvmargs</span><span class="o">=</span><span class="s">-Xmx1536M ;mine have just this line at first</span> +<span class="na">android.useAndroidX</span><span class="o">=</span><span class="s">true ; uses androidX instead of the default support library</span> +<span class="na">android.enableJetifier</span><span class="o">=</span><span class="s">true ; uses jetpack libraries</span> +<span class="na">android.enableR8</span><span class="o">=</span><span class="s">true ; the new code shriker</span> +</code></pre></div> + +<p>After that, voilà, app up and running.</p>Removing a user from SQL Server database who owns a schema2019-09-06T07:00:00-03:002020-10-21T18:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2019-09-06:/removing-user-from-sql-server-database.html<p>Your customer urge you to drop a user from the MsSQL Server database, but you stuck with the following related error:</p> +<div class="highlight"><pre><span></span><code><span class="n">Error</span><span class="o">:</span> <span class="mi">15138</span> <span class="n">The</span> <span class="n">database</span> <span class="n">principal</span> <span class="n">owns</span> <span class="n">a</span> <span class="n">schema</span> <span class="k">in</span> <span class="n">the</span> <span class="n">database</span><span class="o">,</span> <span class="n">and</span> <span class="n">cannot</span> <span class="n">be</span> <span class="n">dropped</span><span class="o">.</span> +</code></pre></div> + +<p>That means that the user owns one or more shcemas of your database. If …</p><p>Your customer urge you to drop a user from the MsSQL Server database, but you stuck with the following related error:</p> +<div class="highlight"><pre><span></span><code><span class="n">Error</span><span class="o">:</span> <span class="mi">15138</span> <span class="n">The</span> <span class="n">database</span> <span class="n">principal</span> <span class="n">owns</span> <span class="n">a</span> <span class="n">schema</span> <span class="k">in</span> <span class="n">the</span> <span class="n">database</span><span class="o">,</span> <span class="n">and</span> <span class="n">cannot</span> <span class="n">be</span> <span class="n">dropped</span><span class="o">.</span> +</code></pre></div> + +<p>That means that the user owns one or more shcemas of your database. If you don't have access to the SSMS to see which schema or objects the user owns, the following SQL should do the job.</p> +<div class="highlight"><pre><span></span><code><span class="k">USE</span><span class="w"> </span><span class="o">[</span><span class="n">DATABASENAME</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> + +<span class="k">select</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Objeto</span><span class="p">,</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Owner</span><span class="w"></span> +<span class="k">from</span><span class="w"> </span><span class="n">sys</span><span class="p">.</span><span class="n">schemas</span><span class="w"> </span><span class="n">so</span><span class="w"></span> +<span class="k">inner</span><span class="w"> </span><span class="k">join</span><span class="w"> </span><span class="n">sysusers</span><span class="w"> </span><span class="n">su</span><span class="w"> </span><span class="k">on</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">principal_id</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">uid</span><span class="w"></span> +<span class="k">where</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">&#39;username&#39;</span><span class="w"></span> + +<span class="k">select</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Objeto</span><span class="p">,</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Owner</span><span class="p">,</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">xtype</span><span class="w"> </span><span class="n">Tipo</span><span class="w"></span> +<span class="k">from</span><span class="w"> </span><span class="n">sys</span><span class="p">.</span><span class="n">sysobjects</span><span class="w"> </span><span class="n">so</span><span class="w"></span> +<span class="k">inner</span><span class="w"> </span><span class="k">join</span><span class="w"> </span><span class="n">sysusers</span><span class="w"> </span><span class="n">su</span><span class="w"> </span><span class="k">on</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">uid</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">uid</span><span class="w"></span> +<span class="k">where</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">&#39;username&#39;</span><span class="w"></span> +</code></pre></div> + +<p>Once you have the objects/schemas owned by the user, you can change them with the following SQL (schema change sample):</p> +<div class="highlight"><pre><span></span><code><span class="k">USE</span><span class="w"> </span><span class="o">[</span><span class="n">DATABASENAME</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +<span class="k">ALTER</span><span class="w"> </span><span class="k">AUTHORIZATION</span><span class="w"> </span><span class="k">ON</span><span class="w"> </span><span class="k">SCHEMA</span><span class="o">::[</span><span class="n">db_datareader</span><span class="o">]</span><span class="w"> </span><span class="k">TO</span><span class="w"> </span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="w"> </span><span class="c1">-- new owner username</span> +<span class="k">ALTER</span><span class="w"> </span><span class="k">AUTHORIZATION</span><span class="w"> </span><span class="k">ON</span><span class="w"> </span><span class="k">SCHEMA</span><span class="o">::[</span><span class="n">db_datawriter</span><span class="o">]</span><span class="w"> </span><span class="k">TO</span><span class="w"> </span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +</code></pre></div> + +<p>Then you're ready to drop the user <code>DROP USER [username]</code></p> +<h2>How to list all the schemas and it's owners?</h2> +<p>Here's a script to list schemas and it's owners.</p> +<div class="highlight"><pre><span></span><code><span class="k">USE</span><span class="w"> </span><span class="o">[</span><span class="n">DATABASENAME</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +<span class="k">SELECT</span><span class="w"></span> +<span class="w"> </span><span class="nf">schema_name</span><span class="p">(</span><span class="nf">schema_id</span><span class="p">)</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="n">schemaname</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="nf">user_name</span><span class="p">(</span><span class="n">schm</span><span class="p">.</span><span class="n">principal_id</span><span class="p">)</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="n">username</span><span class="p">,</span><span class="w"> </span><span class="o">*</span><span class="w"></span> +<span class="k">FROM</span><span class="w"> </span><span class="n">sys</span><span class="p">.</span><span class="n">schemas</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="n">schm</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +</code></pre></div>Limiting Connection Resources on SQL Server2019-08-12T12:00:00-03:002019-08-12T12:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2019-08-12:/limiting-connection-resources-sql-server.html<p>Have you ever suffered from a slow SQLServer database? Someone love to run that heavy query in the database? Resource Governor to the rescue. You can set a few rules on how users (connections actually) will use the server/database resources based on a few things.</p> +<p>First things first, if …</p><p>Have you ever suffered from a slow SQLServer database? Someone love to run that heavy query in the database? Resource Governor to the rescue. You can set a few rules on how users (connections actually) will use the server/database resources based on a few things.</p> +<p>First things first, if you don't have DAC enabled, enable it now. Dealing with resource governor can lock you out of the database and leave you without action (almost... you can start the server with -c -m -f).</p> +<p>Now to understand how Resource Governor works, we have a few keywords <code>resource pool</code>, <code>workload group</code> e <code>Classifier Function</code>.</p> +<p><img alt="Pool Sample" src="/images/sql-pool.png"></p> +<h2>Resource Pool</h2> +<p>First, we have the Resource Pool, with is the bigger resource group that we have the ability to manage. With it, we can set a few things like: <code>MIN_CPU_PERCENT</code>, <code>MAX_CPU_PERCENT</code>, <code>MIN_MEMORY_PERCENT</code>, <code>MAX_MEMORY_PERCENT</code>, <code>MIN_IOPS_PER_VOLUME</code>, and <code>MAX_IOPS_PER_VOLUME</code>.</p> +<p>Be aware that the <code>MAX_CPU_PERCENT</code> will just "works" when there is another connection with a higher priority, otherwise it will use what is available. Let's create a pool.</p> +<div class="highlight"><pre><span></span><code><span class="k">CREATE</span><span class="w"> </span><span class="n">RESOURCE</span><span class="w"> </span><span class="n">POOL</span><span class="w"> </span><span class="o">[</span><span class="n">SpreadSheet</span><span class="o">]</span><span class="w"></span> +<span class="k">WITH</span><span class="w"> </span><span class="p">(</span><span class="w"></span> +<span class="w"> </span><span class="n">MIN_CPU_PERCENT</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">MAX_CPU_PERCENT</span><span class="o">=</span><span class="mi">20</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">MIN_MEMORY_PERCENT</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">MAX_MEMORY_PERCENT</span><span class="o">=</span><span class="mi">20</span><span class="w"></span> +<span class="p">);</span><span class="w"></span> +</code></pre></div> + +<p>## Workload Group</p> +<p>Then we have a workload group that "works" inside a pool, so you can have another granularity on how you can split your resources. Again, we have a few options: <code>IMPORTANCE</code>, <code>REQUEST_MAX_CPU_TIME_SEC</code>, <code>REQUEST_MAX_MEMORY_GRANT_PERCENT</code>, <code>GROUP_MAX_REQUESTS</code>.</p> +<p>The <code>IMPORTANCE</code> set guesses what... the importance of that workload inside the pool, you can set LOW, MEDIUM, HIGH. GROUP_MAX_REQUESTS sets how many requests can run at the same time inside that workload (0 will set as NO LIMIT)</p> +<div class="highlight"><pre><span></span><code><span class="k">CREATE</span><span class="w"> </span><span class="n">WORKLOAD</span><span class="w"> </span><span class="k">GROUP</span><span class="w"> </span><span class="o">[</span><span class="n">DepartmentA</span><span class="o">]</span><span class="w"> </span> +<span class="k">WITH</span><span class="w"> </span><span class="p">(</span><span class="w"></span> +<span class="w"> </span><span class="n">GROUP_MAX_REQUESTS</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">IMPORTANCE</span><span class="o">=</span><span class="n">LOW</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">REQUEST_MAX_CPU_TIME_SEC</span><span class="o">=</span><span class="mi">10</span><span class="p">,</span><span class="w"> </span><span class="c1">-- Time running/using CPU</span> +<span class="w"> </span><span class="n">REQUEST_MAX_MEMORY_GRANT_PERCENT</span><span class="o">=</span><span class="mi">15</span><span class="w"></span> +<span class="p">)</span><span class="w"> </span><span class="k">USING</span><span class="w"> </span><span class="o">[</span><span class="n">SpreadSheet</span><span class="o">]</span><span class="p">;</span><span class="w"> </span><span class="c1">-- pool name here</span> +</code></pre></div> + +<h2>Classifier Function</h2> +<p>This is where everything begins... This is the entry point where you should set the group name. It's a function that will run for every new connection so be aware that if your function runs lots of queries or some heavy stuff... that time will be added to the connection handshake. If the function returns NULL or a group name that doesn't exist, the 'default' group will be used... Yes, there is a default workload group where everything runs where there's no classifier.</p> +<div class="highlight"><pre><span></span><code><span class="k">CREATE</span><span class="w"> </span><span class="k">FUNCTION</span><span class="w"> </span><span class="n">fnClassWorkloadGovernor</span><span class="p">()</span><span class="w"> </span> +<span class="k">RETURNS</span><span class="w"> </span><span class="n">SYSNAME</span><span class="w"> </span><span class="k">WITH</span><span class="w"> </span><span class="n">SCHEMABINDING</span><span class="w"> </span> +<span class="k">AS</span><span class="w"> </span> +<span class="k">BEGIN</span><span class="w"> </span> +<span class="w"> </span><span class="k">IF</span><span class="w"> </span><span class="nf">APP_NAME</span><span class="p">()</span><span class="w"> </span><span class="ow">LIKE</span><span class="w"> </span><span class="s1">&#39;%Excel%&#39;</span><span class="w"></span> +<span class="w"> </span><span class="k">RETURN</span><span class="w"> </span><span class="s1">&#39;DepartmentA&#39;</span><span class="w"></span> + +<span class="w"> </span><span class="k">IF</span><span class="w"> </span><span class="nf">HOST_NAME</span><span class="p">()</span><span class="w"> </span><span class="ow">LIKE</span><span class="w"> </span><span class="s1">&#39;%THAT_MACHINE_OR_APP_SERVER%&#39;</span><span class="w"></span> +<span class="w"> </span><span class="k">RETURN</span><span class="w"> </span><span class="s1">&#39;LowPriority&#39;</span><span class="w"></span> + +<span class="w"> </span><span class="k">RETURN</span><span class="w"> </span><span class="k">NULL</span><span class="w"></span> +<span class="k">END</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> + +<span class="k">ALTER</span><span class="w"> </span><span class="n">RESOURCE</span><span class="w"> </span><span class="n">GOVERNOR</span><span class="w"> </span><span class="k">WITH</span><span class="w"> </span><span class="p">(</span><span class="n">CLASSIFIER_FUNCTION</span><span class="o">=</span><span class="n">dbo</span><span class="p">.</span><span class="n">fnClassWorkloadGovernor</span><span class="p">);</span><span class="w"></span> +<span class="k">ALTER</span><span class="w"> </span><span class="n">RESOURCE</span><span class="w"> </span><span class="n">GOVERNOR</span><span class="w"> </span><span class="k">RECONFIGURE</span><span class="p">;</span><span class="w"></span> +</code></pre></div> + +<p>There you go... now you have a fully working resource governor, but look out that If you want to delete that classifier function, first you have to remove it from the resource governor (look the SCHEMABINDING at the create up there).</p> +<p>To disable Resource Governor</p> +<div class="highlight"><pre><span></span><code><span class="k">ALTER</span><span class="w"> </span><span class="n">RESOURCE</span><span class="w"> </span><span class="n">GOVERNOR</span><span class="w"> </span><span class="k">WITH</span><span class="w"> </span><span class="p">(</span><span class="n">CLASSIFIER_FUNCTION</span><span class="o">=</span><span class="k">null</span><span class="p">)</span><span class="w"></span> +<span class="k">ALTER</span><span class="w"> </span><span class="n">RESOURCE</span><span class="w"> </span><span class="n">GOVERNOR</span><span class="w"> </span><span class="k">RECONFIGURE</span><span class="w"></span> + +<span class="k">ALTER</span><span class="w"> </span><span class="n">RESOURCE</span><span class="w"> </span><span class="n">GOVERNOR</span><span class="w"> </span><span class="n">DISABLE</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +</code></pre></div>Using git hooks to easy your life2019-07-30T20:00:00-03:002019-07-30T20:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2019-07-30:/using_git_hooks_easy_your_life.html<p>Hey folks, it's been a time since my last post. In the meantime, I moved to another state, changed job, and started learning new kinds of stuff. Today I would like to share one thing that I usually do with my small git projects. Git has many cool features, git …</p><p>Hey folks, it's been a time since my last post. In the meantime, I moved to another state, changed job, and started learning new kinds of stuff. Today I would like to share one thing that I usually do with my small git projects. Git has many cool features, git hooks were one of them. I'll talk about the pre-commit hook today.</p> +<p>Let's say that, for some reason, you don't have a CI tool/server running after every commit and you want to enforce that every developer runs the tests before every commit? Git pre-commit to the rescue. You can code the hooks with shell, ruby, python, and I could be wrong, but even PHP would work. pre-commit is a client-side hook (we have server side too) and he's located inside the <cite>.git/hooks</cite> folder. Let's jump to the code... Create a file called 'pre-commit' inside that folder with the following code.</p> +<div class="highlight"><pre><span></span><span class="ch">#!/bin/bash</span> +npm <span class="nb">test</span> <span class="c1"># assuming you&#39;re using it inside a nodeJS project</span> +</pre></div> +<p>Don't forget to make the script executable!! Now break your test and try to commit. That's easy but can save you from breaking the tests at the main CI/Travis/Codeship/etc and being notified by email :). Why not even validate the lint of your project or check if the coverage doesn't fall? Does your team/company have a patter for commit messages? No problem, there is a hook called <cite>commit-msg</cite> that you can use to validate your message.</p> +Microservices with NodeJS, Express.js and RabbitMQ Part 22018-04-13T13:00:00-03:002018-04-13T13:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-04-13:/microservices_nodejs_express_rabbitmq_part_2.html<p>If you haven't read the <a class="reference external" href="https://www.sipmann.com/microservices_nodejs_express_rabbitmq_part_1-en.html">part 1</a> go ahead and read it... It can be useful :). Or if for some reason you want to start now, you can grab the project where we stopped <a class="reference external" href="https://github.com/sipmann/imagecompacter/releases/tag/v1">here</a> and get along. On this part, we'll implement the RabbitMQ queue and see how we …</p><p>If you haven't read the <a class="reference external" href="https://www.sipmann.com/microservices_nodejs_express_rabbitmq_part_1-en.html">part 1</a> go ahead and read it... It can be useful :). Or if for some reason you want to start now, you can grab the project where we stopped <a class="reference external" href="https://github.com/sipmann/imagecompacter/releases/tag/v1">here</a> and get along. On this part, we'll implement the RabbitMQ queue and see how we can get the best of our app and server with that.</p> +<p>Before we began coding, let's understand why we are going to use RabbitMQ if what we have now works? If you check again, you'll see how long it takes to answer the request with the optimized image. It takes a few seconds, so imagine an online service with thousands of request to optimize images (like <a class="reference external" href="https://tinypng.com/">TinyPNG</a>) how long is it gonna take to answer every request? How much of your server is it gonna take? With only one service running, probably the server will crash.</p> +<p>With a queue, we can schedule the requests so we can use the amount of memory and processor that our server has, without taking more than we can. It's better to take a few seconds to answer the request then throw some error to the user. Want more? With RabbitMQ we can see how the queue is doing and we can add more consumers (workers) to it and get things done quicker and distribute the job.</p> +<p>First of all, we need an up and running Rabbit server, for the sake of simplicity, I'll use a Docker container with it inside.</p> +<div class="highlight"><pre><span></span>docker run -d --name rabbit -p <span class="m">5672</span>:5672 -p <span class="m">8080</span>:15672 rabbitmq:3-management +</pre></div> +<p>You can see that we're running the rabbitmq:3-management image, which provides us a web interface to see how things are going. After that, if you look at our code you'll see that all the job is made at the '/upload' route, and that's what we'll change.</p> +<p>First, we need to understand what we need from RabbitMQ. We need something that, we send an image to a queue and get an optimized image back from that. There is a name for that, is RPC (remote procedure call) and there are two ways of doing this with rabbit. Both the ways you can see on their tutorial page. We'll use the approach that uses a global channel whose id is randomly generated (you'll use the name 'amq.rabbitmq.reply-to' but the rabbit will do the job).</p> +<p>Let's start importing the library, defining a few variables and defining a init function that will establish a connection with the rabbit server and create our RPC queue. The RPC queue it's where we'll receive the answer from the consumer (our worker).</p> +<div class="highlight"><pre><span></span><span class="c1">//import the library</span> +<span class="kr">const</span> <span class="nx">amqplib</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;amqplib&#39;</span><span class="p">);</span> + +<span class="c1">//queue channel</span> +<span class="kd">let</span> <span class="nx">channel</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span> +<span class="c1">//queue name</span> +<span class="kr">const</span> <span class="nx">QUEUE</span> <span class="o">=</span> <span class="s1">&#39;optimizeimg&#39;</span><span class="p">;</span> + +<span class="c1">//...</span> + +<span class="kd">function</span> <span class="nx">init</span><span class="p">()</span> <span class="p">{</span> + <span class="k">return</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;amqplib&#39;</span><span class="p">).</span><span class="nx">connect</span><span class="p">(</span><span class="s1">&#39;amqp://localhost&#39;</span><span class="p">)</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">conn</span> <span class="p">=&gt;</span> <span class="nx">conn</span><span class="p">.</span><span class="nx">createChannel</span><span class="p">())</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">ch</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="nx">channel</span> <span class="o">=</span> <span class="nx">ch</span><span class="p">;</span> + + <span class="c1">//this queue is a &quot;Direct reply-to&quot; read more at the docs</span> + <span class="c1">//When some msg comes in, we &quot;emit&quot; a message to the proper &quot;correlationId&quot; listener</span> + <span class="nx">ch</span><span class="p">.</span><span class="nx">consume</span><span class="p">(</span><span class="s1">&#39;amq.rabbitmq.reply-to&#39;</span><span class="p">,</span> <span class="nx">msg</span> <span class="p">=&gt;</span> <span class="nx">eventEmitter</span><span class="p">.</span><span class="nx">emit</span><span class="p">(</span><span class="nx">msg</span><span class="p">.</span><span class="nx">properties</span><span class="p">.</span><span class="nx">correlationId</span><span class="p">,</span> <span class="nx">msg</span><span class="p">.</span><span class="nx">content</span><span class="p">),</span> <span class="p">{</span><span class="nx">noAck</span><span class="o">:</span> <span class="kc">true</span><span class="p">});</span> + <span class="p">});</span> +<span class="p">}</span> + +<span class="c1">//Random id generator</span> +<span class="kd">function</span> <span class="nx">randomid</span><span class="p">()</span> <span class="p">{</span> + <span class="k">return</span> <span class="k">new</span> <span class="nb">Date</span><span class="p">().</span><span class="nx">getTime</span><span class="p">().</span><span class="nx">toString</span><span class="p">()</span> <span class="o">+</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">random</span><span class="p">().</span><span class="nx">toString</span><span class="p">()</span> <span class="o">+</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">random</span><span class="p">().</span><span class="nx">toString</span><span class="p">();</span> +<span class="p">}</span> + +<span class="nx">app</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="s1">&#39;/upload&#39;</span><span class="p">,</span> <span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="kd">let</span> <span class="nx">img</span> <span class="o">=</span> <span class="nx">req</span><span class="p">.</span><span class="nx">files</span><span class="p">.</span><span class="nx">image</span><span class="p">;</span> + + <span class="kd">let</span> <span class="nx">id</span> <span class="o">=</span> <span class="nx">randomid</span><span class="p">();</span> + + <span class="c1">//Event listener that will fire when the proper randomid is provided</span> + <span class="nx">eventEmitter</span><span class="p">.</span><span class="nx">once</span><span class="p">(</span><span class="nx">id</span><span class="p">,</span> <span class="nx">msg</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="nx">res</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="nx">msg</span><span class="p">,</span> <span class="s1">&#39;binary&#39;</span><span class="p">);</span> + <span class="nx">res</span><span class="p">.</span><span class="nx">end</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="s1">&#39;binary&#39;</span><span class="p">);</span> + <span class="p">});</span> + + <span class="c1">//Checks if the queue exists, and create it if needed.</span> + <span class="nx">channel</span><span class="p">.</span><span class="nx">assertQueue</span><span class="p">(</span><span class="nx">QUEUE</span><span class="p">)</span> + <span class="c1">//Sent the buffered img to the queue with the ID and the responseQueue</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="nx">channel</span><span class="p">.</span><span class="nx">sendToQueue</span><span class="p">(</span><span class="nx">QUEUE</span><span class="p">,</span> <span class="nx">img</span><span class="p">.</span><span class="nx">data</span><span class="p">,</span> <span class="p">{</span><span class="nx">correlationId</span><span class="o">:</span><span class="nx">id</span><span class="p">,</span> <span class="nx">replyTo</span><span class="o">:</span> <span class="s1">&#39;amq.rabbitmq.reply-to&#39;</span><span class="p">}));</span> + +<span class="p">});</span> + +<span class="c1">//Finally start the app with the given port number</span> +<span class="c1">//now we initialize the rabbitmq connection before start the server</span> +<span class="nx">init</span><span class="p">()</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="nx">app</span><span class="p">.</span><span class="nx">listen</span><span class="p">(</span><span class="mi">4000</span><span class="p">,</span> <span class="p">()</span> <span class="p">=&gt;</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;Example app listening on port 4000!&#39;</span><span class="p">)))</span> + <span class="p">.</span><span class="k">catch</span><span class="p">(</span><span class="nx">err</span><span class="p">=&gt;</span><span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="nx">err</span><span class="p">));</span> +</pre></div> +<p>Ok, now we have our server code rewritten so let's see our worker code. Create a file named 'worker.js' and let's see how it's gonna be. It's really simple. You initialize a connection with RabbitMQ too, create a channel, check if the queue exists and start watching for incoming messages. When an image arrives, we do the job with it and send back to the &quot;replyTo&quot; queue the optimized image for the proper sender (correlationId). In the end, we do an acknowledge of the message so it get's out from the queue.</p> +<div class="highlight"><pre><span></span><span class="kr">const</span> <span class="nx">imagemin</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;imagemin&#39;</span><span class="p">);</span> +<span class="kr">const</span> <span class="nx">imageminPngquant</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;imagemin-pngquant&#39;</span><span class="p">);</span> + +<span class="kd">let</span> <span class="nx">channel</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span> +<span class="kr">const</span> <span class="nx">QUEUE</span> <span class="o">=</span> <span class="s1">&#39;imgqueue&#39;</span><span class="p">;</span> + +<span class="nx">require</span><span class="p">(</span><span class="s1">&#39;amqplib&#39;</span><span class="p">).</span><span class="nx">connect</span><span class="p">(</span><span class="s1">&#39;amqp://localhost&#39;</span><span class="p">)</span> +<span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">conn</span> <span class="p">=&gt;</span><span class="nx">conn</span><span class="p">.</span><span class="nx">createChannel</span><span class="p">())</span> +<span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">ch</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="nx">ch</span><span class="p">.</span><span class="nx">assertQueue</span><span class="p">(</span><span class="nx">QUEUE</span><span class="p">)</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="c1">//Watch incomming messages</span> + <span class="nx">ch</span><span class="p">.</span><span class="nx">consume</span><span class="p">(</span><span class="nx">QUEUE</span><span class="p">,</span> <span class="nx">msg</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="nx">imagemin</span><span class="p">.</span><span class="nx">buffer</span><span class="p">(</span><span class="nx">msg</span><span class="p">.</span><span class="nx">content</span><span class="p">,</span> <span class="p">{</span> + <span class="nx">plugins</span><span class="o">:</span> <span class="p">[</span><span class="nx">imageminPngquant</span><span class="p">()]</span> + <span class="p">})</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">out</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="c1">//Send back to the sender (replyTo) queue and give the correlationId back</span> + <span class="c1">//so we can emit the event.</span> + <span class="nx">ch</span><span class="p">.</span><span class="nx">sendToQueue</span><span class="p">(</span><span class="nx">msg</span><span class="p">.</span><span class="nx">properties</span><span class="p">.</span><span class="nx">replyTo</span><span class="p">,</span> <span class="nx">out</span><span class="p">,</span> <span class="p">{</span> + <span class="nx">correlationId</span><span class="o">:</span> <span class="nx">msg</span><span class="p">.</span><span class="nx">properties</span><span class="p">.</span><span class="nx">correlationId</span> + <span class="p">});</span> + + <span class="c1">//Acknowledge the job done with the message.</span> + <span class="nx">ch</span><span class="p">.</span><span class="nx">ack</span><span class="p">(</span><span class="nx">msg</span><span class="p">);</span> + <span class="p">});</span> + <span class="p">});</span> + <span class="p">});</span> +<span class="p">});</span> +</pre></div> +<p>The key points here are. Open just one connection to the hole server. You CAN create one channel for every request that you receive, but it can take some time if you have a really big cluster of RabbitMQ. It was a quick tutorial, but I hope that it was able to clear a few questions that you might have when working with rabbit and express.</p> +Microservices with NodeJS, Express.js and RabbitMQ Part 12018-04-04T11:25:00-03:002018-04-04T11:25:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-04-04:/microservices_nodejs_express_rabbitmq_part_1.html<p>This is the first part of a microservices development series. The service will consist of the bellow architecture, where we will expose an image optimizer service that will forward the request to a <a class="reference external" href="https://www.rabbitmq.com/">RabbitMQ</a> queue and answer with the bytecode of the optimized image. It shouldn't be a long series …</p><p>This is the first part of a microservices development series. The service will consist of the bellow architecture, where we will expose an image optimizer service that will forward the request to a <a class="reference external" href="https://www.rabbitmq.com/">RabbitMQ</a> queue and answer with the bytecode of the optimized image. It shouldn't be a long series so let's see what we can do.</p> +<img alt="Service architecture" src="/images/microservices_rabit_pt1.png" /> +<p>Let's get our environment working. First, we'll need to install the libraries that we'll use.</p> +<p>Create a dir and initialize the nodejs application inside it (<cite>npm init</cite>) and then let's install the deps.</p> +<ul class="simple"> +<li>amqplib - AMQP lib to interact with rabbitmq</li> +<li>express - Do our basic rest API</li> +<li>express-fileupload - easy file upload parser</li> +<li>imagemin and imagemin-pngquant - our image compacter</li> +</ul> +<div class="highlight"><pre><span></span>npm install --save express amqplib express-fileupload imagemin imagemin-pngquant +</pre></div> +<p>Now let's write the entry points for our service, we'll have two basic entry points. The path <cite>/</cite> that will have a welcome message, the second path will be <cite>/upload</cite> and this is the one that will handle the image and produce a job for our workers.</p> +<div class="highlight"><pre><span></span><span class="kr">const</span> <span class="nx">express</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;express&#39;</span><span class="p">);</span> +<span class="kr">const</span> <span class="nx">fileUpload</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;express-fileupload&#39;</span><span class="p">);</span> + +<span class="c1">//Instantiate the app and set the fileupload parser to manage files</span> +<span class="kr">const</span> <span class="nx">app</span> <span class="o">=</span> <span class="nx">express</span><span class="p">();</span> +<span class="nx">app</span><span class="p">.</span><span class="nx">use</span><span class="p">(</span><span class="nx">fileUpload</span><span class="p">());</span> + +<span class="c1">//Our index entry point</span> +<span class="nx">app</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;/&#39;</span><span class="p">,</span> <span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="nx">res</span><span class="p">.</span><span class="nx">send</span><span class="p">(</span><span class="s1">&#39;Hello From ImageCompacter service&#39;</span><span class="p">));</span> + +<span class="c1">//The path that will handle the image file and throw them to the queue</span> +<span class="nx">app</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="s1">&#39;/upload&#39;</span><span class="p">,</span> <span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="c1">//With express-fileupload we can grab the files like this</span> + <span class="kd">let</span> <span class="nx">img</span> <span class="o">=</span> <span class="nx">req</span><span class="p">.</span><span class="nx">files</span><span class="p">.</span><span class="nx">image</span><span class="p">;</span> <span class="c1">//&quot;image&quot; is the name of the input</span> + + <span class="nx">res</span><span class="p">.</span><span class="nx">send</span><span class="p">(</span><span class="s1">&#39;Not ready yet&#39;</span><span class="p">);</span> +<span class="p">});</span> + +<span class="c1">//Finally start the app with the given port number</span> +<span class="nx">app</span><span class="p">.</span><span class="nx">listen</span><span class="p">(</span><span class="mi">4000</span><span class="p">,</span> <span class="p">()</span> <span class="p">=&gt;</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;Example app listening on port 4000!&#39;</span><span class="p">));</span> +</pre></div> +<p>Let's check if it works, run the service with node.</p> +<div class="highlight"><pre><span></span>node index.js +Example app listening on port <span class="m">4000</span>! +</pre></div> +<p>Open the browser and check if it prints our hello message when accessing <cite>localhost:4000</cite>. Works? Greate. Now let's work with the image and see how we do it. To optimize our image, we'll use the library imagemin and <a class="reference external" href="https://www.npmjs.com/package/imagemin-pngquant">imagemin-pngquant</a>, it will be that simple for now, we'll work with rabbitmq latter.</p> +<div class="highlight"><pre><span></span><span class="kr">const</span> <span class="nx">imagemin</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;imagemin&#39;</span><span class="p">);</span> +<span class="kr">const</span> <span class="nx">imageminPngquant</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;imagemin-pngquant&#39;</span><span class="p">);</span> +<span class="c1">//...</span> + +<span class="c1">//The path that will handle the image file and throw them to the queue</span> +<span class="nx">app</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="s1">&#39;/upload&#39;</span><span class="p">,</span> <span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="kd">let</span> <span class="nx">img</span> <span class="o">=</span> <span class="nx">req</span><span class="p">.</span><span class="nx">files</span><span class="p">.</span><span class="nx">image</span><span class="p">;</span> <span class="c1">//&quot;image&quot; is the name of the input</span> + + <span class="nx">imagemin</span><span class="p">.</span><span class="nx">buffer</span><span class="p">(</span><span class="nx">img</span><span class="p">.</span><span class="nx">data</span><span class="p">,</span> <span class="p">{</span> + <span class="nx">plugins</span><span class="o">:</span> <span class="p">[</span><span class="nx">imageminPngquant</span><span class="p">()]</span> + <span class="p">})</span> + <span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">out</span> <span class="p">=&gt;</span> <span class="p">{</span> + <span class="nx">res</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="nx">out</span><span class="p">,</span><span class="s1">&#39;binary&#39;</span><span class="p">);</span> + <span class="nx">res</span><span class="p">.</span><span class="nx">end</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="s1">&#39;binary&#39;</span><span class="p">);</span> + <span class="p">});</span> +<span class="p">});</span> + + <span class="c1">//...</span> +</pre></div> +<p>Use <a class="reference external" href="https://www.getpostman.com/">Postman</a> to test the request. To see if it will work, make a request to <cite>http://localhost:4000/upload</cite> with a formdata with a file. Select the &quot;send and Download&quot; instead of &quot;Send&quot; and you should have an image after that. Bellow an image of how your postman should be.</p> +<img alt="Postman" src="/images/microservice_postman.png" /> +<p>That's it for today, next week we'll change our code to use RabbitMQ.</p> +Connecting to a database through SSH2018-03-29T10:03:00-03:002018-03-29T10:03:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-03-29:/connecting_to_database_through_ssh.html<p>If someday, for some reason, you need to establish a connection with a database which is behind a firewall and you only have SSH access on that server (and you don't want to use a CLI) you can do an SSH tunnel. It's pretty simple, bellow has a sample of …</p><p>If someday, for some reason, you need to establish a connection with a database which is behind a firewall and you only have SSH access on that server (and you don't want to use a CLI) you can do an SSH tunnel. It's pretty simple, bellow has a sample of how to allow connections to a remote Firebird database.</p> +<div class="highlight"><pre><span></span>ssh -L <span class="m">3051</span>:192.168.1.9:3050 username@192.168.1.9 +</pre></div> +<p>The <cite>-L</cite> parameter tells to SSH do a local port forwarding on local port <cite>3051</cite> to remote port <cite>3050</cite>. You can use it to a connection with many services, not just databases.</p> +<p>You can do the reverse kind of tunnel, forward connections from the host to your local machine, you just have to change the parameter form &quot;-L&quot; to &quot;-R&quot; and the port order is inverted, first come the port where the server will listen and after your localhost port. This remote port forwarding must be enabled on the server. Look for <cite>GatewayPorts</cite> at the ssh config file.</p> +<div class="highlight"><pre><span></span>ssh -R <span class="m">3050</span>:localhost:3050 username@192.168.1.9 +</pre></div> +<p>Why whould you need something like that?? Let's say you want to share a localhost site/database with a friend, but your internet connection don't allow you to expose any port but you have access to a remote server witch can do that. Problem solved ;).</p> +Now posting on Grepora2018-03-24T00:40:00-03:002018-03-24T00:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-03-24:/now_posting_on_grepora.html<p>A few weeks ago I started posting at <a class="reference external" href="https://grepora.com/blog/">Grepora</a> blog. If you like or are looking for some Oracle related stuff, Grepora it's a good place to go and spend a time reading :). From time to time I'll be posting there, it doesn't mean that this blog will be closed …</p><p>A few weeks ago I started posting at <a class="reference external" href="https://grepora.com/blog/">Grepora</a> blog. If you like or are looking for some Oracle related stuff, Grepora it's a good place to go and spend a time reading :). From time to time I'll be posting there, it doesn't mean that this blog will be closed or anything like that, but probably this one will be more focused on Front-end stuff, a few tricks with linux and a lil less with Java.</p> +Scaffolding a React app with Parcel and Yeoman2018-03-17T13:00:00-03:002018-03-17T13:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-03-17:/scaffolding_react_app_with_parcel_yeoman.html<p>Since <a class="reference external" href="https://parceljs.org/">Parcel JS</a> arrived, I've been using it a lot as an awesome alternative for WebPack. Webpack isn't bad but IMO it's too complex for the job and parcel do the same (at least the basic) with almost zero configuration. But if you need to create many apps (like a …</p><p>Since <a class="reference external" href="https://parceljs.org/">Parcel JS</a> arrived, I've been using it a lot as an awesome alternative for WebPack. Webpack isn't bad but IMO it's too complex for the job and parcel do the same (at least the basic) with almost zero configuration. But if you need to create many apps (like a react app) over and over again, it get's a lil boring following the basic steps.</p> +<div class="highlight"><pre><span></span>npm init -y +npm install --save react +npm install --save react-dom +npm install --save-dev parcel-bundler +npm install --save-dev babel-preset-env +npm install --save-dev babel-preset-react + +<span class="c1">#create .babelrc file</span> +<span class="c1">#create html, css, jsx files</span> + +parcel index.html +</pre></div> +<p>It's not a hard job, a simple shell script do the job, but what if you need some IFs when creating the app, or even change a few things at the <cite>package.json</cite>? A shell script still does the job, but come on... There is a better way. <a class="reference external" href="http://yeoman.io/">Yeoman</a> is here for you. I've already <a class="reference external" href="https://www.sipmann.com/desenvolvendo-app-firefoxos-pt.html">talked about it</a> on another post (Portuguese post).</p> +<p>Straight to the point, I've released a Yeoman generator to get the things a lil quicker. The name is <a class="reference external" href="https://www.npmjs.com/package/generator-parcel-react">generator-parcel-react</a> and it still lacks a few things that I will deal with soon. It's pretty simple to use it.</p> +<div class="highlight"><pre><span></span><span class="c1">#First time only</span> +npm install -g yo +npm install -g generator-parcel-react + +<span class="c1">#every time you create a new app</span> +yo parcel-react +</pre></div> +<p>And that's it. Right now you can scaffold and app with React, SASS and React Router. Hope you like it and feel free to ask new features.</p> +Could not open connection with MySQL and Hibernate2018-03-09T12:35:00-03:002018-03-09T12:35:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-03-09:/cloud-not-open-connection-java-mysql-hibernate.html<p>Last day I decided to deploy a MySQL Docker image to work with my Java application. I've been using PostgreSQL instead and have no problems at all, but after I moved to MySQL, the app didn't connect anymore with the database and throw some &quot;Could not open connection&quot; at my …</p><p>Last day I decided to deploy a MySQL Docker image to work with my Java application. I've been using PostgreSQL instead and have no problems at all, but after I moved to MySQL, the app didn't connect anymore with the database and throw some &quot;Could not open connection&quot; at my face, but why? I've tried to connect to it manually and got the same problem.</p> +<p>After some research, I found that the true error should be java.sql.SQLException: null, message from server: &quot;Host '172.17.0.4' is not allowed to connect to this MySQL server&quot; but it wasn't showing to me...</p> +<p>After all, be aware that with the docker image MySQL:5.7.21 (latest version right now) the root user isn't allowed to remote connect to the database (it's alright, security reasons) and if you still want to do remote connections to it with root there are a few things you can do.</p> +<ol class="arabic simple"> +<li>Create a user or allow root to access from other IPs.</li> +</ol> +<div class="highlight"><pre><span></span><span class="o">#</span><span class="k">No</span> <span class="k">access</span> <span class="k">to</span> <span class="k">user</span> <span class="n">root</span> <span class="k">on</span> <span class="k">any</span> <span class="n">other</span> <span class="n">IP</span> +<span class="k">SELECT</span> <span class="k">User</span><span class="p">,</span> <span class="k">Host</span> <span class="k">FROM</span> <span class="n">mysql</span><span class="p">.</span><span class="k">user</span><span class="p">;</span> +<span class="o">+</span><span class="c1">---------------+-----------+</span> +<span class="o">|</span> <span class="k">User</span> <span class="o">|</span> <span class="k">Host</span> <span class="o">|</span> +<span class="o">+</span><span class="c1">---------------+-----------+</span> +<span class="o">|</span> <span class="n">healthchecker</span> <span class="o">|</span> <span class="n">localhost</span> <span class="o">|</span> +<span class="o">|</span> <span class="n">root</span> <span class="o">|</span> <span class="n">localhost</span> <span class="o">|</span> +<span class="o">+</span><span class="c1">---------------+-----------+</span> +<span class="mi">2</span> <span class="k">rows</span> <span class="k">in</span> <span class="k">set</span> <span class="p">(</span><span class="mi">0</span><span class="p">.</span><span class="mi">01</span> <span class="n">sec</span><span class="p">)</span> + +<span class="k">CREATE</span> <span class="k">USER</span> <span class="s1">&#39;newuser&#39;</span><span class="o">@</span><span class="s1">&#39;%&#39;</span> <span class="n">IDENTIFIED</span> <span class="k">BY</span> <span class="s1">&#39;password&#39;</span><span class="p">;</span> <span class="o">#%</span> <span class="n">mean</span> <span class="k">any</span> <span class="n">IP</span> +<span class="k">GRANT</span> <span class="k">ALL</span> <span class="k">PRIVILEGES</span> <span class="k">ON</span> <span class="o">*</span><span class="p">.</span><span class="o">*</span> <span class="k">TO</span> <span class="s1">&#39;newuser&#39;</span><span class="o">@</span><span class="s1">&#39;%&#39;</span><span class="p">;</span> <span class="o">#*</span><span class="p">.</span><span class="o">*</span> <span class="n">mean</span> <span class="k">database</span><span class="p">.</span><span class="k">table</span> <span class="p">;)</span> +</pre></div> +<ol class="arabic simple" start="2"> +<li>Use MariaDB instead, witch come (at least on the version 10.2.13) with root allowed to do remote connections and will work like MySQL :)</li> +</ol> +<p>I changed to <a class="reference external" href="https://mariadb.org/">MariaDB</a> as it work without creating user or any changes on the Java code or the <cite>docker run command</cite>.</p> +Solving java.net.SocketException: Protocol family unavailable on a Java + Docker + WildFly2018-03-04T17:40:00-03:002018-03-04T17:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-03-04:/socketException-protocol-family-unavailable-java-docker-wildfly.html<p>On the last days I've been playing with <a class="reference external" href="http://wildfly-swarm.io/">WildFly Swarm</a> and I decided to deploy a simple app with Docker. Should work fine, at least that was what I thought. Built a container with the following Dockerfile and instead of a working web app, all that I got was the …</p><p>On the last days I've been playing with <a class="reference external" href="http://wildfly-swarm.io/">WildFly Swarm</a> and I decided to deploy a simple app with Docker. Should work fine, at least that was what I thought. Built a container with the following Dockerfile and instead of a working web app, all that I got was the error <cite>java.net.SocketException: Protocol family unavailable</cite>.</p> +<div class="highlight"><pre><span></span><span class="k">FROM</span> <span class="s">java:openjdk-8-jdk</span> + +<span class="k">COPY</span> target/issues.jar /opt/issues.jar + +<span class="k">EXPOSE</span><span class="s"> 8080</span> + +<span class="k">CMD</span> <span class="p">[</span><span class="s2">&quot;java&quot;</span><span class="p">,</span><span class="s2">&quot;-jar&quot;</span><span class="p">,</span><span class="s2">&quot;/opt/issues.jar&quot;</span><span class="p">]</span> +</pre></div> +<p>For some reason, WildFly and Java decided to use the IPv6 network interface from Docker instead the v4, so all you have to do is tell Java to prefer IPv4 instead with the following configuration option in your pom.xml file inside your WildFly plugin.</p> +<div class="highlight"><pre><span></span><span class="nt">&lt;plugin&gt;</span> + <span class="nt">&lt;groupId&gt;</span>org.wildfly.swarm<span class="nt">&lt;/groupId&gt;</span> + <span class="nt">&lt;artifactId&gt;</span>wildfly-swarm-plugin<span class="nt">&lt;/artifactId&gt;</span> + <span class="nt">&lt;version&gt;</span>2018.2.0<span class="nt">&lt;/version&gt;</span> + + <span class="c">&lt;!-- ADD THIS --&gt;</span> + <span class="nt">&lt;configuration&gt;</span> + <span class="nt">&lt;mainClass&gt;</span>org.wildfly.swarm.examples.netflix.ribbon.frontend.Main<span class="nt">&lt;/mainClass&gt;</span> + <span class="nt">&lt;properties&gt;</span> + <span class="nt">&lt;java.net.preferIPv4Stack&gt;</span>true<span class="nt">&lt;/java.net.preferIPv4Stack&gt;</span> + <span class="nt">&lt;/properties&gt;</span> + <span class="nt">&lt;/configuration&gt;</span> +</pre></div> +<p>Another way to solve is adding the same properties to the run command at the Dockerfile, so you choose where you'll add it. Bellow the Dockerfile solution.</p> +<div class="highlight"><pre><span></span><span class="k">FROM</span> <span class="s">java:openjdk-8-jdk</span> +<span class="k">ENV</span> <span class="nv">JAVA_OPTS</span><span class="o">=</span><span class="s2">&quot;-Djava.net.preferIPv4Stack=true -Djava.net.preferIPv4Addresses=true&quot;</span> + +<span class="k">COPY</span> target/issues.jar /opt/issues.jar + +<span class="k">EXPOSE</span><span class="s"> 8080</span> + +<span class="k">ENTRYPOINT</span> <span class="nb">exec</span> java <span class="nv">$JAVA_OPTS</span> -jar /opt/issues.jar +</pre></div> +Change display settings on linux with Disper2018-02-27T12:40:00-03:002018-02-27T12:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-02-27:/linux-external-display-with-disper.html<p>From time to time, I change the Linux distro on my laptop or just do a fresh install on it. And once in a while, have random problems with external displays. It can be something really &quot;simple&quot; like don't detecting the external monitor or something crazy like the image below …</p><p>From time to time, I change the Linux distro on my laptop or just do a fresh install on it. And once in a while, have random problems with external displays. It can be something really &quot;simple&quot; like don't detecting the external monitor or something crazy like the image below.</p> +<img alt="Display bug" src="/images/bug.png" /> +<p>As you can see at the image, the mint detected the display but mirrored it in a crazy way that works but doesn't at the same time. If you try anything and doesn't get working, or just wanna skip the whole job of configuring complexes text files, give a try to <a class="reference external" href="http://willem.engen.nl/projects/disper/">Disper</a>. Download the latest version. +Extract it on any folder, and make install it (on the extracted folder).</p> +<div class="highlight"><pre><span></span>make install +</pre></div> +<p>After that, you can start using it... There are a few options that will serve you well.</p> +<div class="highlight"><pre><span></span>disper -e <span class="c1">#extend your display</span> +</pre></div> +<div class="highlight"><pre><span></span>disper -c <span class="c1">#clone your display</span> +</pre></div> +<div class="highlight"><pre><span></span>disper -s <span class="c1">#only your external display</span> +</pre></div> +Java - Files.readAllBytes throws OutOfMemory2018-02-17T13:00:00-02:002018-02-17T13:00:00-02:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-02-17:/reading-files-java-readAllBytes-outofmemory.html<p>When you need to interact with files, there's the possibility to read all bytes from the file with <cite>Files.readAllBytes</cite>. But be aware of the kinds of files your application will deal with because the Java API files have a limit for the buffer that is defined as <cite>Integer.MAX_VALUE …</cite></p><p>When you need to interact with files, there's the possibility to read all bytes from the file with <cite>Files.readAllBytes</cite>. But be aware of the kinds of files your application will deal with because the Java API files have a limit for the buffer that is defined as <cite>Integer.MAX_VALUE</cite> as you can see above or at the OpenJDK sources.</p> +<div class="highlight"><pre><span></span><span class="kd">public</span> <span class="kd">static</span> <span class="kt">byte</span><span class="o">[]</span> <span class="nf">readAllBytes</span><span class="p">(</span><span class="n">Path</span> <span class="n">path</span><span class="p">)</span> <span class="kd">throws</span> <span class="n">IOException</span> <span class="p">{</span> + <span class="k">try</span> <span class="p">(</span><span class="n">FileChannel</span> <span class="n">fc</span> <span class="o">=</span> <span class="n">FileChannel</span><span class="p">.</span><span class="na">open</span><span class="p">(</span><span class="n">path</span><span class="p">))</span> <span class="p">{</span> + <span class="kt">long</span> <span class="n">size</span> <span class="o">=</span> <span class="n">fc</span><span class="p">.</span><span class="na">size</span><span class="p">();</span> + <span class="k">if</span> <span class="p">(</span><span class="n">size</span> <span class="o">&gt;</span> <span class="p">(</span><span class="kt">long</span><span class="p">)</span><span class="n">Integer</span><span class="p">.</span><span class="na">MAX_VALUE</span><span class="p">)</span> + <span class="k">throw</span> <span class="k">new</span> <span class="n">OutOfMemoryError</span><span class="p">(</span><span class="s">&quot;Required array size too large&quot;</span><span class="p">);</span> + + <span class="kt">byte</span><span class="o">[]</span> <span class="n">arr</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">byte</span><span class="o">[</span><span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">size</span><span class="o">]</span><span class="p">;</span> + <span class="n">ByteBuffer</span> <span class="n">bb</span> <span class="o">=</span> <span class="n">ByteBuffer</span><span class="p">.</span><span class="na">wrap</span><span class="p">(</span><span class="n">arr</span><span class="p">);</span> + <span class="k">while</span> <span class="p">(</span><span class="n">bb</span><span class="p">.</span><span class="na">hasRemaining</span><span class="p">())</span> <span class="p">{</span> + <span class="k">if</span> <span class="p">(</span><span class="n">fc</span><span class="p">.</span><span class="na">read</span><span class="p">(</span><span class="n">bb</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> + <span class="c1">// truncated</span> + <span class="k">break</span><span class="p">;</span> + <span class="p">}</span> + <span class="p">}</span> + + <span class="kt">int</span> <span class="n">nread</span> <span class="o">=</span> <span class="n">bb</span><span class="p">.</span><span class="na">position</span><span class="p">();</span> + <span class="k">return</span> <span class="p">(</span><span class="n">nread</span> <span class="o">==</span> <span class="n">size</span><span class="p">)</span> <span class="o">?</span> <span class="n">arr</span> <span class="p">:</span> <span class="n">Arrays</span><span class="p">.</span><span class="na">copyOf</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="n">nread</span><span class="p">);</span> + <span class="p">}</span> +<span class="p">}</span> +</pre></div> +<p>With that in mind, check if isn't better read chunks of bytes e work with that slice in exchange of loading the whole file into the memory ;). Above a simple example of how you can read chunks of bytes from the file.</p> +<div class="highlight"><pre><span></span><span class="kt">byte</span><span class="o">[]</span> <span class="n">buffer</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">byte</span><span class="o">[</span><span class="mi">1024</span><span class="o">]</span><span class="p">;</span> +<span class="n">FileInputStream</span> <span class="n">in</span> <span class="o">=</span> <span class="k">new</span> <span class="n">FileInputStream</span><span class="p">(</span><span class="n">file</span><span class="p">);</span> +<span class="kt">int</span> <span class="n">rc</span> <span class="o">=</span> <span class="n">in</span><span class="p">.</span><span class="na">read</span><span class="p">(</span><span class="n">buffer</span><span class="p">);</span> +<span class="k">while</span> <span class="p">(</span><span class="n">rc</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span> +<span class="p">{</span> + <span class="c1">//crazy stuff here with buffer</span> + <span class="n">rc</span> <span class="o">=</span> <span class="n">in</span><span class="p">.</span><span class="na">read</span><span class="p">(</span><span class="n">buffer</span><span class="p">);</span> +<span class="p">}</span> +</pre></div> + \ No newline at end of file diff --git a/feeds/mauricio-camargo-sipmann.atom.xml.gz b/feeds/mauricio-camargo-sipmann.atom.xml.gz new file mode 100644 index 000000000..560275035 Binary files /dev/null and b/feeds/mauricio-camargo-sipmann.atom.xml.gz differ diff --git a/feeds/mauricio-camargo-sipmann.rss.xml b/feeds/mauricio-camargo-sipmann.rss.xml new file mode 100644 index 000000000..a99ad4a74 --- /dev/null +++ b/feeds/mauricio-camargo-sipmann.rss.xml @@ -0,0 +1,28 @@ + +Sipmann - Maurício Camargo Sipmannhttps://www.sipmann.com/Mon, 21 Dec 2020 13:30:00 -0300Monitoring MySQL restarts with PowerShellhttps://www.sipmann.com/monitoring-mysql-restarts-with-powershell.html<p>Hey folks, it's time for another PowerShell script. If you haven't seen the other ones, check the links below.</p> +<ul> +<li><a href="https://www.sipmann.com/en/monitoring-mysql-replication-with-powershell.html">Monitoring MySQL replication with PowerShell</a></li> +</ul> +<p>Well, this one it's a pretty simple script, but again, if your customer doesn't have a Zabbix server or doesn't allow you to setup one to …</p>Maurício Camargo SipmannMon, 21 Dec 2020 13:30:00 -0300tag:www.sipmann.com,2020-12-21:/monitoring-mysql-restarts-with-powershell.htmlPowerShellMySQLMySQL RestartPowershell monitoringChanging a MySQL user password across multiple application instances without downtimehttps://www.sipmann.com/mysql-dual-password-functionality.html<p>Do you need to change the password of a MySQL user that it's being used in an application, and can't allow a single downtime? Well, MySQL 8.0.14 came with a feature called <a href="https://dev.mysql.com/doc/refman/8.0/en/password-management.html#dual-passwords">Dual Password Support</a>, with it you can change the password keeping the previous password as a …</p>Maurício Camargo SipmannWed, 09 Dec 2020 13:40:00 -0300tag:www.sipmann.com,2020-12-09:/mysql-dual-password-functionality.htmlMySQLMySQLMySQL Dual PasswordApache Nifi JSON to SQL Replacing underscorehttps://www.sipmann.com/apache-nifi-json-to-sql-replacing-underscore.html<p>Recently I was doing some ETL with Apache NiFi. But after a few minutes of drawing my flow, I saw that the component ConvertJSONToSQL was replacing the underscore ('_') from the field name in the where condition (I was preparing an Update SQL). That was weird because, at the set …</p>Maurício Camargo SipmannWed, 02 Dec 2020 14:00:00 -0300tag:www.sipmann.com,2020-12-02:/apache-nifi-json-to-sql-replacing-underscore.htmlToolsApache NifiConvertJSONToSQLreplacing underscoreBlocking a user on SQL Server based on a schedulehttps://www.sipmann.com/blocking-user-on-sql-server-based-on-schedule.html<p>Ok, some time ago, I've posted about how you can set limits to connections on SQL Server using the <a href="https://www.sipmann.com/limiting-connection-resources-sql-server.html#.X6Cz8IhKhPY">Resource Governor</a>. But what if you can't use it? You always can block logins using a login trigger, but I don't like the idea of having selects running on every login …</p>Maurício Camargo SipmannSat, 14 Nov 2020 07:00:00 -0300tag:www.sipmann.com,2020-11-14:/blocking-user-on-sql-server-based-on-schedule.htmlSQL ServerSQLServerUserTime Schedule blockingHow to set columns on select using Entity Frameworkhttps://www.sipmann.com/select_specific_fields_with_efcore.html<p>So, you use Entity Framework Core, and you usually code your selects like the following, maybe you are getting too much data.</p> +<div class="highlight"><pre><span></span><code><span class="kt">var</span> <span class="n">products</span> <span class="p">=</span> <span class="n">Products</span> + <span class="p">.</span><span class="n">Where</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span> <span class="p">&gt;</span> <span class="m">0</span><span class="p">)</span> + <span class="p">.</span><span class="n">OrderBy</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">)</span> + <span class="p">.</span><span class="n">ToList</span><span class="p">()</span> +</code></pre></div> + +<p>Running the query above, on my table, you'll get the following output, take a look …</p>Maurício Camargo SipmannWed, 28 Oct 2020 19:00:00 -0300tag:www.sipmann.com,2020-10-28:/select_specific_fields_with_efcore.html.NETDotNetDotNet CoreEntity FrameworkEF CoreSpecify columnsZabbix Running on Low Memory Modehttps://www.sipmann.com/zabbix-running-on-low-memory-mode.html<p>Hey folks, another Zabbix post today. This one it's about increasing the Zabbix Server Cache. It's pretty common (if you have the default settings only) get a warning about your <code>Zabbix value cache running on low memory mode</code> at your dashboard or logs.</p> +<p><img alt="Zabbix Dashboard warning about the memory problem" src="/images/zabbix_low_memory_mode.png"> +<img alt="Zabbix Dashboard cache graph 70% used" src="/images/zabbix_cache_filling.png"></p> +<p>To solve, go back to your Zabbix …</p>Maurício Camargo SipmannTue, 20 Oct 2020 19:00:00 -0300tag:www.sipmann.com,2020-10-20:/zabbix-running-on-low-memory-mode.htmlLinuxZabbixShellLow memoryCacheMonitoring MySQL Replication Status with PowerShellhttps://www.sipmann.com/monitoring-mysql-replication-with-powershell.html<p>I've been migration some bash scripts that I have to PowerShell, and it's time to migrate a script that monitors the replication of a MySQL database. The credit for the original script goes to <a href="https://handyman.dulare.com/mysql-replication-status-alerts-with-bash-script/">Paweł</a>. It's a simple script where I seek a few tags/fields that we get from …</p>Maurício Camargo SipmannWed, 14 Oct 2020 19:00:00 -0300tag:www.sipmann.com,2020-10-14:/monitoring-mysql-replication-with-powershell.htmlPowerShellMySQLMySQL ReplicationPowerShellPowershell mailMicrosoft Against Covidhttps://www.sipmann.com/microsoft-against-covid.html<p>Has your job been affected by covid? Well, last week I've posted on <a href="https://grepora.com/2020/09/17/microsoft-ignite-certification-voucher/">Grepora</a> about a Free Certification Voucher that Microsoft was giving away at the Microsoft Ignite event. After that, I found that they were also giving a huge discount to people who have had their job affected by …</p>Maurício Camargo SipmannSat, 03 Oct 2020 19:00:00 -0300tag:www.sipmann.com,2020-10-03:/microsoft-against-covid.htmlAzureAzureCertificationMicrosoftThe power of PowerShellhttps://www.sipmann.com/the-power-of-powershell.html<p>As a long time Linux user, I've automated a few things with bash scripts and stayed away from PowerShell... I've moved to a Windows environment a few years ago and still, haven gave a shot to PS. But why not? I've made a few scripts to automate some tasks at …</p>Maurício Camargo SipmannMon, 21 Sep 2020 19:00:00 -0300tag:www.sipmann.com,2020-09-21:/the-power-of-powershell.htmlPowerShellAzurePowerShellScriptGetChild-ItemRemove-ItemStop-ProccessTop Level Statement in C# 9https://www.sipmann.com/top_level_statement_csharp_9.html<p>Hey folks, I'm coming along to tell you a few things about the new feature of C# 9. Every time you want to start a new project, you always have the same Main File, with the same structure. At the next version of C# (version 9), we'll have a new …</p>Maurício Camargo SipmannWed, 29 Jul 2020 19:00:00 -0300tag:www.sipmann.com,2020-07-29:/top_level_statement_csharp_9.html.NETC#Dotnet CoreDotNet.netZabbix poller processes more than 75%https://www.sipmann.com/zabbix-poller-processes-more-than-75.html<p>Hey folks, this is the third post about tweaking the Zabbix configurations. All changes that I've suggested here were based on a Zabbix Server with 50+ hosts. Another thing that can happen to your server, it's the poller get overwhelmed by the amount of servers that need to be polled …</p>Maurício Camargo SipmannThu, 02 Jul 2020 19:00:00 -0300tag:www.sipmann.com,2020-07-02:/zabbix-poller-processes-more-than-75.htmlLinuxZabbixShellZabbix PollerPoller proccess more than 75%Monitoring a Website heath with Azure Functionshttps://www.sipmann.com/monitoring-website-heath-with-azure-functions.html<p>Sometimes you get your self in need to monitor a website's health or it's content for changes. Of course, there's plenty of options out there, but for the sake of curiosity, let's code our own to see what we can do. First things first. Everything you'll see here, you can …</p>Maurício Camargo SipmannMon, 22 Jun 2020 19:00:00 -0300tag:www.sipmann.com,2020-06-22:/monitoring-website-heath-with-azure-functions.htmlAzureAzureAzure DevopsC#Dotnet CoreDotNetMonitor WebsiteAzure Data Fundamentals certification with 80% discounthttps://www.sipmann.com/azure-data-fundamentals-certification-80-discount.html<p>Hey folks, if you want to achieve some certification this year, keep an eye open for vouchers. A few months ago, Oracle released a set of free courses with certifications. Now it's Microsoft time. Microsoft is updating they're certifications and we have a voucher of 80% discount using the coupon …</p>Maurício Camargo SipmannTue, 09 Jun 2020 12:30:00 -0300tag:www.sipmann.com,2020-06-09:/azure-data-fundamentals-certification-80-discount.htmlAzureAzureAzure FundamentalsAzure CertificationDiscountZabbix ICMP pinger processes more than 75%https://www.sipmann.com/zabbix-icmp-pinger-processes-more-than-75.html<p>So your monitoring sytems have grown and your zabbix started loggin "Zabbix icmp pinger processes more than 75% busy" at the dashboard.</p> +<p><img alt="Dashboard do zabbix avisando sobre o erro" src="/images/zabbix_pinger01.png"></p> +<p>All you have to do is open your config file (<code>/etc/zabbix/zabbix_server.conf</code>) and find the a tag named <code>StartPingers</code>. It'll be commented by default. Uncomment it …</p>Maurício Camargo SipmannMon, 25 May 2020 16:00:00 -0300tag:www.sipmann.com,2020-05-25:/zabbix-icmp-pinger-processes-more-than-75.htmlLinuxZabbixicmp pingericmp pinger more than 75Zabbix ServerZabbix Server Out of Memoryhttps://www.sipmann.com/zabbix-server-out-of-memory-crash.html<p>Do you have a crashing Zabbix Server and looking through the log <code>/var/log/zabbix/zabbix_server.log</code> you see the following out of memory message?</p> +<div class="highlight"><pre><span></span><code>__mem_malloc: skipped <span class="m">0</span> asked <span class="m">24</span> skip_min <span class="m">18446744073709551615</span> skip_max <span class="m">0</span> +<span class="o">[</span>file:dbconfig.c,line:94<span class="o">]</span> __zbx_mem_realloc<span class="o">()</span>: out of memory <span class="o">(</span>requested <span class="m">16</span> bytes<span class="o">)</span> +<span class="o">[</span>file:dbconfig.c,line …</code></pre></div>Maurício Camargo SipmannThu, 27 Feb 2020 19:00:00 -0300tag:www.sipmann.com,2020-02-27:/zabbix-server-out-of-memory-crash.htmlLinuxZabbixShellOut of memoryCrashFlutter + firebase auth crashinghttps://www.sipmann.com/flutter_with_firebase_auth_crashing.html<p>Hey Folks, recently I've started learning <a href="https://flutter.dev/">Flutter</a> and right after a TODO List, I tried a Firebase integration. But as soon as I started setting the dependencies, my app stopped opening... just a crash. After a few logs digging, I've found the following log.</p> +<div class="highlight"><pre><span></span><code>AndroidRuntime: FATAL EXCEPTION: main +AndroidRuntime: Process …</code></pre></div>Maurício Camargo SipmannThu, 03 Oct 2019 19:00:00 -0300tag:www.sipmann.com,2019-10-03:/flutter_with_firebase_auth_crashing.htmlFlutterflutterfirebaseArrayMapNoClassDefFoundRemoving a user from SQL Server database who owns a schemahttps://www.sipmann.com/removing-user-from-sql-server-database.html<p>Your customer urge you to drop a user from the MsSQL Server database, but you stuck with the following related error:</p> +<div class="highlight"><pre><span></span><code><span class="n">Error</span><span class="o">:</span> <span class="mi">15138</span> <span class="n">The</span> <span class="n">database</span> <span class="n">principal</span> <span class="n">owns</span> <span class="n">a</span> <span class="n">schema</span> <span class="k">in</span> <span class="n">the</span> <span class="n">database</span><span class="o">,</span> <span class="n">and</span> <span class="n">cannot</span> <span class="n">be</span> <span class="n">dropped</span><span class="o">.</span> +</code></pre></div> + +<p>That means that the user owns one or more shcemas of your database. If …</p>Maurício Camargo SipmannFri, 06 Sep 2019 07:00:00 -0300tag:www.sipmann.com,2019-09-06:/removing-user-from-sql-server-database.htmlSQL ServerSQLServerUserThe database principal owns a schemaLimiting Connection Resources on SQL Serverhttps://www.sipmann.com/limiting-connection-resources-sql-server.html<p>Have you ever suffered from a slow SQLServer database? Someone love to run that heavy query in the database? Resource Governor to the rescue. You can set a few rules on how users (connections actually) will use the server/database resources based on a few things.</p> +<p>First things first, if …</p>Maurício Camargo SipmannMon, 12 Aug 2019 12:00:00 -0300tag:www.sipmann.com,2019-08-12:/limiting-connection-resources-sql-server.htmlSQL ServerSQLServerResource GovernorUsing git hooks to easy your lifehttps://www.sipmann.com/using_git_hooks_easy_your_life.html<p>Hey folks, it's been a time since my last post. In the meantime, I moved to another state, changed job, and started learning new kinds of stuff. Today I would like to share one thing that I usually do with my small git projects. Git has many cool features, git …</p>Maurício Camargo SipmannTue, 30 Jul 2019 20:00:00 -0300tag:www.sipmann.com,2019-07-30:/using_git_hooks_easy_your_life.htmltoolsgitshellpre-commithooksMicroservices with NodeJS, Express.js and RabbitMQ Part 2https://www.sipmann.com/microservices_nodejs_express_rabbitmq_part_2.html<p>If you haven't read the <a class="reference external" href="https://www.sipmann.com/microservices_nodejs_express_rabbitmq_part_1-en.html">part 1</a> go ahead and read it... It can be useful :). Or if for some reason you want to start now, you can grab the project where we stopped <a class="reference external" href="https://github.com/sipmann/imagecompacter/releases/tag/v1">here</a> and get along. On this part, we'll implement the RabbitMQ queue and see how we …</p>Maurício Camargo SipmannFri, 13 Apr 2018 13:00:00 -0300tag:www.sipmann.com,2018-04-13:/microservices_nodejs_express_rabbitmq_part_2.htmlFront-endnodejsmicroservicesrabbitmqexpressjsimageminimagemin-pngquantnode jsMicroservices with NodeJS, Express.js and RabbitMQ Part 1https://www.sipmann.com/microservices_nodejs_express_rabbitmq_part_1.html<p>This is the first part of a microservices development series. The service will consist of the bellow architecture, where we will expose an image optimizer service that will forward the request to a <a class="reference external" href="https://www.rabbitmq.com/">RabbitMQ</a> queue and answer with the bytecode of the optimized image. It shouldn't be a long series …</p>Maurício Camargo SipmannWed, 04 Apr 2018 11:25:00 -0300tag:www.sipmann.com,2018-04-04:/microservices_nodejs_express_rabbitmq_part_1.htmlFront-endnodejsmicroservicesrabbitmqexpressjsimageminimagemin-pngquantnode jsConnecting to a database through SSHhttps://www.sipmann.com/connecting_to_database_through_ssh.html<p>If someday, for some reason, you need to establish a connection with a database which is behind a firewall and you only have SSH access on that server (and you don't want to use a CLI) you can do an SSH tunnel. It's pretty simple, bellow has a sample of …</p>Maurício Camargo SipmannThu, 29 Mar 2018 10:03:00 -0300tag:www.sipmann.com,2018-03-29:/connecting_to_database_through_ssh.htmlLinuxopensshtunnelssh tunnelsshthrough firewallNow posting on Greporahttps://www.sipmann.com/now_posting_on_grepora.html<p>A few weeks ago I started posting at <a class="reference external" href="https://grepora.com/blog/">Grepora</a> blog. If you like or are looking for some Oracle related stuff, Grepora it's a good place to go and spend a time reading :). From time to time I'll be posting there, it doesn't mean that this blog will be closed …</p>Maurício Camargo SipmannSat, 24 Mar 2018 00:40:00 -0300tag:www.sipmann.com,2018-03-24:/now_posting_on_grepora.htmlRandomGreporaRandomScaffolding a React app with Parcel and Yeomanhttps://www.sipmann.com/scaffolding_react_app_with_parcel_yeoman.html<p>Since <a class="reference external" href="https://parceljs.org/">Parcel JS</a> arrived, I've been using it a lot as an awesome alternative for WebPack. Webpack isn't bad but IMO it's too complex for the job and parcel do the same (at least the basic) with almost zero configuration. But if you need to create many apps (like a …</p>Maurício Camargo SipmannSat, 17 Mar 2018 13:00:00 -0300tag:www.sipmann.com,2018-03-17:/scaffolding_react_app_with_parcel_yeoman.htmlFront-endnodejsyeomanparcelreactCould not open connection with MySQL and Hibernatehttps://www.sipmann.com/cloud-not-open-connection-java-mysql-hibernate.html<p>Last day I decided to deploy a MySQL Docker image to work with my Java application. I've been using PostgreSQL instead and have no problems at all, but after I moved to MySQL, the app didn't connect anymore with the database and throw some &quot;Could not open connection&quot; at my …</p>Maurício Camargo SipmannFri, 09 Mar 2018 12:35:00 -0300tag:www.sipmann.com,2018-03-09:/cloud-not-open-connection-java-mysql-hibernate.htmlJavaJavaMySQLHibernateSolving java.net.SocketException: Protocol family unavailable on a Java + Docker + WildFlyhttps://www.sipmann.com/socketException-protocol-family-unavailable-java-docker-wildfly.html<p>On the last days I've been playing with <a class="reference external" href="http://wildfly-swarm.io/">WildFly Swarm</a> and I decided to deploy a simple app with Docker. Should work fine, at least that was what I thought. Built a container with the following Dockerfile and instead of a working web app, all that I got was the …</p>Maurício Camargo SipmannSun, 04 Mar 2018 17:40:00 -0300tag:www.sipmann.com,2018-03-04:/socketException-protocol-family-unavailable-java-docker-wildfly.htmlJavaJavaWildFlyDockerjava.net.SocketExceptionProtocol family unavailableChange display settings on linux with Disperhttps://www.sipmann.com/linux-external-display-with-disper.html<p>From time to time, I change the Linux distro on my laptop or just do a fresh install on it. And once in a while, have random problems with external displays. It can be something really &quot;simple&quot; like don't detecting the external monitor or something crazy like the image below …</p>Maurício Camargo SipmannTue, 27 Feb 2018 12:40:00 -0300tag:www.sipmann.com,2018-02-27:/linux-external-display-with-disper.htmlLinuxLinuxexternal displaydisperJava - Files.readAllBytes throws OutOfMemoryhttps://www.sipmann.com/reading-files-java-readAllBytes-outofmemory.html<p>When you need to interact with files, there's the possibility to read all bytes from the file with <cite>Files.readAllBytes</cite>. But be aware of the kinds of files your application will deal with because the Java API files have a limit for the buffer that is defined as <cite>Integer.MAX_VALUE …</cite></p>Maurício Camargo SipmannSat, 17 Feb 2018 13:00:00 -0200tag:www.sipmann.com,2018-02-17:/reading-files-java-readAllBytes-outofmemory.htmlJavaJavaFiles.readAllBytesoutOfMemory \ No newline at end of file diff --git a/feeds/mauricio-camargo-sipmann.rss.xml.gz b/feeds/mauricio-camargo-sipmann.rss.xml.gz new file mode 100644 index 000000000..910650868 Binary files /dev/null and b/feeds/mauricio-camargo-sipmann.rss.xml.gz differ diff --git a/feeds/mysql.atom.xml b/feeds/mysql.atom.xml new file mode 100644 index 000000000..972f49c57 --- /dev/null +++ b/feeds/mysql.atom.xml @@ -0,0 +1,14 @@ + +Sipmann - MySQLhttps://www.sipmann.com/2020-12-09T13:40:00-03:00Changing a MySQL user password across multiple application instances without downtime2020-12-09T13:40:00-03:002020-12-09T13:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-12-09:/mysql-dual-password-functionality.html<p>Do you need to change the password of a MySQL user that it's being used in an application, and can't allow a single downtime? Well, MySQL 8.0.14 came with a feature called <a href="https://dev.mysql.com/doc/refman/8.0/en/password-management.html#dual-passwords">Dual Password Support</a>, with it you can change the password keeping the previous password as a …</p><p>Do you need to change the password of a MySQL user that it's being used in an application, and can't allow a single downtime? Well, MySQL 8.0.14 came with a feature called <a href="https://dev.mysql.com/doc/refman/8.0/en/password-management.html#dual-passwords">Dual Password Support</a>, with it you can change the password keeping the previous password as a kind of backup. That way you still can log in using the old password or can start using the new one. With that, the password change workflow it's the following.</p> +<p>1) Change password keeping the old one;</p> +<p>2) Deploy the new config to your app/cluster;</p> +<p>3) Discard the old password.</p> +<p>To change the password and keep the old one, you have the following command.</p> +<div class="highlight"><pre><span></span><code><span class="k">ALTER</span> <span class="n">USER</span> <span class="s1">&#39;appuser&#39;</span><span class="o">@</span><span class="s1">&#39;localhost&#39;</span> <span class="n">IDENTIFIED</span> <span class="k">BY</span> <span class="s1">&#39;new_password&#39;</span> <span class="n">RETAIN</span> <span class="n">CURRENT</span> <span class="n">PASSWORD</span><span class="p">;</span> +</code></pre></div> + +<p>To discard the old one, run the following.</p> +<div class="highlight"><pre><span></span><code><span class="k">ALTER</span> <span class="n">USER</span> <span class="s1">&#39;appuser&#39;</span><span class="o">@</span><span class="s1">&#39;localhost&#39;</span> <span class="n">DISCARD</span> <span class="n">OLD</span> <span class="n">PASSWORD</span><span class="p">;</span> +</code></pre></div> + +<p>And you are done. Hope you find it as useful as I :)</p> \ No newline at end of file diff --git a/feeds/mysql.atom.xml.gz b/feeds/mysql.atom.xml.gz new file mode 100644 index 000000000..052f886a6 Binary files /dev/null and b/feeds/mysql.atom.xml.gz differ diff --git a/feeds/net.atom.xml b/feeds/net.atom.xml new file mode 100644 index 000000000..a2488bb3d --- /dev/null +++ b/feeds/net.atom.xml @@ -0,0 +1,59 @@ + +Sipmann - .NEThttps://www.sipmann.com/2020-10-28T19:00:00-03:00How to set columns on select using Entity Framework2020-10-28T19:00:00-03:002020-10-28T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-28:/select_specific_fields_with_efcore.html<p>So, you use Entity Framework Core, and you usually code your selects like the following, maybe you are getting too much data.</p> +<div class="highlight"><pre><span></span><code><span class="kt">var</span> <span class="n">products</span> <span class="p">=</span> <span class="n">Products</span> + <span class="p">.</span><span class="n">Where</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span> <span class="p">&gt;</span> <span class="m">0</span><span class="p">)</span> + <span class="p">.</span><span class="n">OrderBy</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">)</span> + <span class="p">.</span><span class="n">ToList</span><span class="p">()</span> +</code></pre></div> + +<p>Running the query above, on my table, you'll get the following output, take a look …</p><p>So, you use Entity Framework Core, and you usually code your selects like the following, maybe you are getting too much data.</p> +<div class="highlight"><pre><span></span><code><span class="kt">var</span> <span class="n">products</span> <span class="p">=</span> <span class="n">Products</span> + <span class="p">.</span><span class="n">Where</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span> <span class="p">&gt;</span> <span class="m">0</span><span class="p">)</span> + <span class="p">.</span><span class="n">OrderBy</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">)</span> + <span class="p">.</span><span class="n">ToList</span><span class="p">()</span> +</code></pre></div> + +<p>Running the query above, on my table, you'll get the following output, take a look at how many columns you are getting back from your database.</p> +<p><img alt="Screenshot with every single column" src="/images/ef_core_allcolumns.png"></p> +<p>In my case, I only care about the Title, PublishedData, and a small description. So to get back only these fields, we have a few options. In the first one, we'll set the fields and return them as a dynamic object, the second one, is to give the .NET a class to use. </p> +<div class="highlight"><pre><span></span><code><span class="kt">var</span> <span class="n">products</span> <span class="p">=</span> <span class="n">Products</span> + + <span class="p">.</span><span class="n">Select</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="k">new</span> <span class="p">{</span><span class="n">p</span><span class="p">.</span><span class="n">ProductID</span><span class="p">,</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">,</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span><span class="p">,</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitPrice</span><span class="p">})</span> + <span class="c1">//.Select(p =&gt; new ProductDTO {p.ProductID, p.ProductName, p.UnitsInStock, p.UnitPrice})</span> + + <span class="p">.</span><span class="n">Where</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span> <span class="p">&gt;</span> <span class="m">0</span><span class="p">)</span> + <span class="p">.</span><span class="n">OrderBy</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">)</span> + <span class="p">.</span><span class="n">ToList</span><span class="p">()</span> +</code></pre></div> + +<p><img alt="Screenshot with fewer columns and also fewer data size" src="/images/ef_core_less_columns.png"></p>Top Level Statement in C# 92020-07-29T19:00:00-03:002020-07-29T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-07-29:/top_level_statement_csharp_9.html<p>Hey folks, I'm coming along to tell you a few things about the new feature of C# 9. Every time you want to start a new project, you always have the same Main File, with the same structure. At the next version of C# (version 9), we'll have a new …</p><p>Hey folks, I'm coming along to tell you a few things about the new feature of C# 9. Every time you want to start a new project, you always have the same Main File, with the same structure. At the next version of C# (version 9), we'll have a new feature called <code>Top Level Statement</code>. With that, we'll be able to code our app without any namespace/class/public void static main structure. Take a look at the code below.</p> +<div class="highlight"><pre><span></span><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span> + +<span class="n">Console</span><span class="p">.</span><span class="n">WriteLine</span><span class="p">(</span><span class="s">&quot;Hello World!&quot;</span><span class="p">);</span> +</code></pre></div> + +<p>It looks pretty simple, but with this, you can play around with your code, and even code a simple/tiny Web API. To start playing with the new features, firstly download the <a href="https://dotnet.microsoft.com/download/dotnet/5.0">.net 5 SDK</a> and change your <code>.csproj</code> file to target the .net 5 and language preview like bellow.</p> +<div class="highlight"><pre><span></span><code><span class="nt">&lt;Project</span> <span class="na">Sdk=</span><span class="s">&quot;Microsoft.NET.Sdk&quot;</span><span class="nt">&gt;</span> + <span class="nt">&lt;PropertyGroup&gt;</span> + <span class="nt">&lt;OutputType&gt;</span>Exe<span class="nt">&lt;/OutputType&gt;</span> + <span class="nt">&lt;TargetFramework&gt;</span>net5.0<span class="nt">&lt;/TargetFramework&gt;</span> + <span class="nt">&lt;LangVersion&gt;</span>preview<span class="nt">&lt;/LangVersion&gt;</span> + <span class="nt">&lt;/PropertyGroup&gt;</span> +<span class="nt">&lt;/Project&gt;</span> +</code></pre></div> + +<p>And you're ready to play with the awesome features available in the preview. Let's code a way to get the image of the day from NASA API and print the Picture of the Day. No awesome code here, it's really a way to show how simple a simple call could be. After here, why not save the image in a file? Maybe send the file over telegram?</p> +<div class="highlight"><pre><span></span><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Net.Http</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Text.Json</span><span class="p">;</span> + +<span class="kt">var</span> <span class="n">API</span> <span class="p">=</span> <span class="s">&quot;https://api.nasa.gov/planetary/apod?hd=true&amp;api_key=DEMO_KEY&quot;</span><span class="p">;</span> +<span class="kt">var</span> <span class="n">cli</span> <span class="p">=</span> <span class="k">new</span> <span class="n">HttpClient</span><span class="p">();</span> + +<span class="kt">var</span> <span class="n">response</span> <span class="p">=</span> <span class="k">await</span> <span class="n">cli</span><span class="p">.</span><span class="n">GetAsync</span><span class="p">(</span><span class="n">API</span><span class="p">);</span> +<span class="kt">var</span> <span class="n">data</span> <span class="p">=</span> <span class="n">JsonSerializer</span><span class="p">.</span><span class="n">Deserialize</span><span class="p">&lt;</span><span class="n">NasaApi</span><span class="p">&gt;(</span><span class="k">await</span> <span class="n">response</span><span class="p">.</span><span class="n">Content</span><span class="p">.</span><span class="n">ReadAsStringAsync</span><span class="p">());</span> + +<span class="n">Console</span><span class="p">.</span><span class="n">WriteLine</span><span class="p">(</span><span class="n">data</span><span class="p">.</span><span class="n">Url</span><span class="p">);</span> +</code></pre></div> + +<p>That's it for today folks. Keep an eye open for the awesome features C# 9 will bring to us, there's plenty more features already available.</p> \ No newline at end of file diff --git a/feeds/net.atom.xml.gz b/feeds/net.atom.xml.gz new file mode 100644 index 000000000..bf1f67bfd Binary files /dev/null and b/feeds/net.atom.xml.gz differ diff --git a/feeds/powershell.atom.xml b/feeds/powershell.atom.xml new file mode 100644 index 000000000..3b2a0dea6 --- /dev/null +++ b/feeds/powershell.atom.xml @@ -0,0 +1,124 @@ + +Sipmann - PowerShellhttps://www.sipmann.com/2020-12-21T13:30:00-03:00Monitoring MySQL restarts with PowerShell2020-12-21T13:30:00-03:002020-12-21T13:30:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-12-21:/monitoring-mysql-restarts-with-powershell.html<p>Hey folks, it's time for another PowerShell script. If you haven't seen the other ones, check the links below.</p> +<ul> +<li><a href="https://www.sipmann.com/en/monitoring-mysql-replication-with-powershell.html">Monitoring MySQL replication with PowerShell</a></li> +</ul> +<p>Well, this one it's a pretty simple script, but again, if your customer doesn't have a Zabbix server or doesn't allow you to setup one to …</p><p>Hey folks, it's time for another PowerShell script. If you haven't seen the other ones, check the links below.</p> +<ul> +<li><a href="https://www.sipmann.com/en/monitoring-mysql-replication-with-powershell.html">Monitoring MySQL replication with PowerShell</a></li> +</ul> +<p>Well, this one it's a pretty simple script, but again, if your customer doesn't have a Zabbix server or doesn't allow you to setup one to do the monitoring, a set of scripts can be handy. We start executing some basic query <code>SHOW GLOBAL STATUS LIKE 'Uptime'</code>, with that we'll get exactly what we're looking for.</p> +<p>If for some reason, the command fails (watch for the "global" variable called <code>$lastExitCode</code>), we send an e-mail telling you about that connection problem.</p> +<p>And then, we get to the part where we parse the value, this one is pretty similar to the parse we did on the first post about using PowerShell to monitor MySQL. But we basically look for the Value line, split it by space and then parse the second position to an integer. And then all we have to do is check if the uptime is lower than our threshold, if it is we send an e-mail.</p> +<div class="highlight"><pre><span></span><code><span class="nv">$MailFrom</span> <span class="p">=</span> <span class="s1">&#39;maurio[at]sipmann.com&#39;</span> +<span class="nv">$MailTo</span> <span class="p">=</span> <span class="s1">&#39;mauricio[at]sipmann.com&#39;</span> +<span class="nv">$MysqlHost</span> <span class="p">=</span> <span class="s1">&#39;127.0.0.1&#39;</span> +<span class="nv">$MysqlUser</span> <span class="p">=</span> <span class="s1">&#39;root&#39;</span> +<span class="nv">$MysqlPass</span> <span class="p">=</span> <span class="s1">&#39;123&#39;</span> + + +<span class="nv">$data</span> <span class="p">=</span> <span class="p">$(</span><span class="n">mysql</span> <span class="n">-h</span> <span class="nv">$MysqlHost</span> <span class="n">-u</span> <span class="nv">$MysqlUser</span> <span class="n">-p</span><span class="s2">&quot;$MysqlPass&quot;</span> <span class="n">-e</span> <span class="s2">&quot;SHOW GLOBAL STATUS LIKE &#39;Uptime&#39; \G&quot;</span><span class="p">)</span> + +<span class="cm">&lt;# Unable to execute the sql Command #&gt;</span> +<span class="k">if</span> <span class="p">(</span><span class="nv">$lastExitCode</span> <span class="o">-eq</span> <span class="n">1</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Send-MailMessage</span> <span class="n">-To</span> <span class="nv">$MailTo</span> <span class="n">-From</span> <span class="nv">$MailFrom</span> <span class="n">-Subject</span> <span class="s1">&#39;Connection problem&#39;</span> <span class="n">-bodyAsHtml</span> <span class="s2">&quot;Connection problem on host ${MysqlHost}&quot;</span> <span class="n">-Credential</span> <span class="nb">Get-Credential</span> <span class="n">-SmtpServer</span> <span class="s1">&#39;smtp.office365.com&#39;</span> <span class="n">-Port</span> <span class="n">587</span> <span class="n">-UseSsl</span> + <span class="n">exit</span> +<span class="p">}</span> + +<span class="nv">$UpTime</span> <span class="p">=</span> <span class="no">[int]</span><span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Value:&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> + +<span class="cm">&lt;# If the uptime is lower then 20 minutes #&gt;</span> +<span class="k">if</span> <span class="p">(</span><span class="nv">$UpTime</span> <span class="o">-lt</span> <span class="n">1200</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Send-MailMessage</span> <span class="n">-To</span> <span class="nv">$MailTo</span> <span class="n">-From</span> <span class="nv">$MailFrom</span> <span class="n">-Subject</span> <span class="s2">&quot;MySQL Restarted&quot;</span> <span class="n">-bodyAsHtml</span> <span class="s2">&quot;MySQL host ${MysqlHost} restarted less than 20 minutes ago&quot;</span> <span class="n">-Credential</span> <span class="nb">Get-Credential</span> <span class="n">-SmtpServer</span> <span class="s1">&#39;smtp.office365.com&#39;</span> <span class="n">-Port</span> <span class="n">587</span> <span class="n">-UseSsl</span> +<span class="p">}</span> +</code></pre></div> + +<p>This script (and the other ones I use) is available at my GitHub <a href="https://github.com/sipmann/PowerShellScripts">here</a>. Keep in mind that the ones on the GitHub repo, are a little different from here.</p>Monitoring MySQL Replication Status with PowerShell2020-10-14T19:00:00-03:002020-10-14T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-14:/monitoring-mysql-replication-with-powershell.html<p>I've been migration some bash scripts that I have to PowerShell, and it's time to migrate a script that monitors the replication of a MySQL database. The credit for the original script goes to <a href="https://handyman.dulare.com/mysql-replication-status-alerts-with-bash-script/">Paweł</a>. It's a simple script where I seek a few tags/fields that we get from …</p><p>I've been migration some bash scripts that I have to PowerShell, and it's time to migrate a script that monitors the replication of a MySQL database. The credit for the original script goes to <a href="https://handyman.dulare.com/mysql-replication-status-alerts-with-bash-script/">Paweł</a>. It's a simple script where I seek a few tags/fields that we get from <code>SHOW SLAVE STATUS\G</code> command, the fields are. <code>Slave_IO_Running</code>, <code>Slave_SQL_Running</code>, and <code>Seconds_Behind_Master</code>. I still need to figure out the proper way to store/read variables like usernames and passwords, if you have any tips, feel free to even make a pull request (<a href="https://github.com/sipmann/PowerShellScripts">here</a>) at the git where I'll store some scripts.</p> +<div class="highlight"><pre><span></span><code><span class="cm">&lt;#</span> +<span class="cm"> Variables definition</span> +<span class="cm">#&gt;</span> +<span class="nv">$MaxSeconds</span> <span class="p">=</span> <span class="n">120</span> <span class="c"># Max seconds behind master allowed</span> +<span class="nv">$MysqlUser</span> <span class="p">=</span> <span class="s1">&#39;root&#39;</span> +<span class="nv">$MysqlPass</span> <span class="p">=</span> <span class="s1">&#39;&#39;</span> + +<span class="nv">$MailTo</span> <span class="p">=</span> <span class="s1">&#39;mauricio@sipmann.com&#39;</span> +<span class="nv">$MailFrom</span> <span class="p">=</span> <span class="s1">&#39;mauricio@sipmann.com&#39;</span> + + +<span class="nv">$data</span> <span class="p">=</span> <span class="p">$(</span><span class="n">mysql</span> <span class="n">-u</span> <span class="nv">$MysqlUser</span> <span class="n">-p</span><span class="s2">&quot;$MysqlPass&quot;</span> <span class="n">-e</span> <span class="s1">&#39;SHOW SLAVE STATUS \G&#39;</span><span class="p">)</span> + +<span class="c">#Debug data</span> +<span class="c">#$data = Get-Content &#39;c:\temp\sampleresult.txt&#39;</span> + +<span class="cm">&lt;# Parse the data #&gt;</span> +<span class="nv">$IORunning</span> <span class="p">=</span> <span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Slave_IO_Running:&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> +<span class="nv">$SQLRunning</span> <span class="p">=</span> <span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Slave_SQL_Running:&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> +<span class="nv">$LastErrNo</span> <span class="p">=</span> <span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Last_Errno&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> +<span class="nv">$SecondsBh</span> <span class="p">=</span> <span class="no">[int]</span><span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Seconds_Behind_Master&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> + +<span class="k">If</span> <span class="p">(</span><span class="nv">$IORunning</span> <span class="o">-Eq</span> <span class="s1">&#39;No&#39;</span> <span class="o">-Or</span> <span class="nv">$SQLRunning</span> <span class="o">-Eq</span> <span class="s1">&#39;No&#39;</span> <span class="o">-Or</span> <span class="nv">$SecondsBh</span> <span class="o">-gt</span> <span class="nv">$MaxSeconds</span><span class="p">)</span> <span class="p">{</span> + <span class="nv">$MailBody</span> <span class="p">=</span> <span class="s1">&#39;&lt;h1&gt;Problema na replicação&lt;/h1&gt;&lt;br&gt;&#39;</span> + + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39; IO Running: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$IORunning</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39; SQL Running: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$SQLRunning</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39;Seconds Behind: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$SecondsBh</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39; Last Err No: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$LastErrNo</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + + <span class="cm">&lt;# Send e-mail, maybe some telegram message here too #&gt;</span> + <span class="nb">Send-MailMessage</span> <span class="n">-To</span> <span class="nv">$MailTo</span> <span class="n">-From</span> <span class="nv">$MailFrom</span> <span class="n">-Subject</span> <span class="s1">&#39;Problemas na replicação&#39;</span> <span class="n">-bodyAsHtml</span> <span class="nv">$MailBody</span> <span class="n">-Credential</span> <span class="p">(</span><span class="nb">Get-Credential</span><span class="p">)</span> <span class="n">-SmtpServer</span> <span class="s1">&#39;smtp.office365.com&#39;</span> <span class="n">-Port</span> <span class="n">587</span> <span class="n">-UseSsl</span> +<span class="p">}</span> <span class="k">Else</span> <span class="p">{</span> + <span class="nb">Write-Host</span> <span class="s2">&quot;Up and running&quot;</span> +<span class="p">}</span> +</code></pre></div>The power of PowerShell2020-09-21T19:00:00-03:002020-09-21T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-09-21:/the-power-of-powershell.html<p>As a long time Linux user, I've automated a few things with bash scripts and stayed away from PowerShell... I've moved to a Windows environment a few years ago and still, haven gave a shot to PS. But why not? I've made a few scripts to automate some tasks at …</p><p>As a long time Linux user, I've automated a few things with bash scripts and stayed away from PowerShell... I've moved to a Windows environment a few years ago and still, haven gave a shot to PS. But why not? I've made a few scripts to automate some tasks at a Protheus server.</p> +<p>I found the PS scripts being easy to read and understand. Bellow, we have a script to remove files filtering their extension (or no extension at all like the following script). </p> +<div class="highlight"><pre><span></span><code><span class="nb">Get-ChildItem</span> <span class="s2">&quot;C:\TOTVS\protheus_data\system&quot;</span> <span class="o">-File</span> <span class="n">-Filter</span> <span class="p">*.</span> <span class="p">|</span> <span class="nb">Move-Item</span> <span class="n">-Force</span> <span class="n">-Destination</span> <span class="p">{</span> + <span class="cm">&lt;# Diretory where the files will be moved. You can use Date formats to help name it #&gt;</span> + <span class="cm">&lt;# LastWriteTime proprtie from the current file #&gt;</span> + <span class="nv">$dir</span> <span class="p">=</span> <span class="s2">&quot;C:\bad_files\{0:yyyy\\MM\\dd}&quot;</span> <span class="o">-f</span> <span class="nv">$_</span><span class="p">.</span><span class="n">LastWriteTime</span> + <span class="nv">$null</span> <span class="p">=</span> <span class="n">mkdir</span> <span class="nv">$dir</span> <span class="n">-Force</span> + <span class="s2">&quot;$dir\</span><span class="p">$(</span><span class="nv">$_</span><span class="p">.</span><span class="n">Name</span><span class="p">)</span><span class="s2">&quot;</span> +<span class="p">}</span> +</code></pre></div> + +<p>Have you ever been in the need to remove files based on other file content? Bello a script where I read a file that has the names of files that I want to remove. </p> +<div class="highlight"><pre><span></span><code><span class="k">foreach</span><span class="p">(</span><span class="nv">$line</span> <span class="k">in</span> <span class="nb">Get-Content</span> <span class="p">.\</span><span class="n">Desktop</span><span class="p">\</span><span class="n">bad_files</span><span class="p">.</span><span class="n">txt</span><span class="p">)</span> <span class="p">{</span> + <span class="k">if</span> <span class="p">(</span><span class="nb">Test-Path</span><span class="p">(</span><span class="s1">&#39;\\x.y.z.a\c$\TOTVS\protheus_data\xmls\&#39;</span><span class="p">+</span><span class="nv">$line</span><span class="p">+</span><span class="s1">&#39;.xml&#39;</span><span class="p">))</span> <span class="p">{</span> + <span class="nb">Remove-Item</span><span class="p">(</span><span class="s1">&#39;\\x.y.z.a\c$\TOTVS\protheus_data\xmls\&#39;</span><span class="p">+</span><span class="nv">$line</span><span class="p">+</span><span class="s1">&#39;.xml&#39;</span><span class="p">)</span> + <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> + <span class="nb">echo </span><span class="nv">$line</span> <span class="p">+</span> <span class="s1">&#39; - File not found&#39;</span> + <span class="p">}</span> +<span class="p">}</span> +</code></pre></div> + +<p>And a bonus script to stop/start services (if you handle some Protheus Server, you know why I do that).</p> +<div class="highlight"><pre><span></span><code><span class="nv">$servicesNames</span> <span class="p">=</span> <span class="s1">&#39;app_main&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker1&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker2&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker3&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker4&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker5&#39;</span> + +<span class="nb">Write-host</span> <span class="s2">&quot;Stoping Services&quot;</span> +<span class="nb">Write-host</span> <span class="s2">&quot;--------------------------&quot;</span> + +<span class="k">foreach</span> <span class="p">(</span><span class="nv">$srv</span> <span class="k">in</span> <span class="nv">$servicesNames</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Write-host</span> <span class="s2">&quot;Stopping: &quot;</span> <span class="p">+</span> <span class="nv">$srv</span> + <span class="nv">$SrvPID</span> <span class="p">=</span> <span class="p">(</span><span class="nb">get-wmiobject</span> <span class="n">win32_service</span> <span class="p">|</span> <span class="nb">where </span><span class="p">{</span> <span class="nv">$_</span><span class="p">.</span><span class="n">name</span> <span class="o">-eq</span> <span class="nv">$srv</span><span class="p">}).</span><span class="n">processID</span> + <span class="nb">Write-host</span> <span class="s2">&quot;PID: &quot;</span> <span class="p">+</span> <span class="nv">$SrvPID</span> + + <span class="cm">&lt;# Force if the proccess is stucked #&gt;</span> + <span class="nb">Stop-Process</span> <span class="nv">$SrvPID</span> <span class="n">-Force</span> + <span class="nb">Write-host</span> <span class="s2">&quot;PDI &quot;</span> <span class="p">+</span> <span class="nv">$SrvPID</span> <span class="p">+</span> <span class="s2">&quot; stopped&quot;</span> +<span class="p">}</span> + + +<span class="nb">Write-host</span> <span class="s2">&quot;Starting Services&quot;</span> +<span class="nb">Write-host</span> <span class="s2">&quot;--------------------------&quot;</span> + +<span class="k">foreach</span> <span class="p">(</span><span class="nv">$srv</span> <span class="k">in</span> <span class="nv">$servicesNames</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Write-host</span> <span class="s2">&quot;Starting: &quot;</span> <span class="p">+</span> <span class="nv">$srv</span> + <span class="nb">Start-Service</span> <span class="nv">$srv</span> +<span class="p">}</span> +</code></pre></div> + +<p>Do you have any automated script? Share with us :)</p> \ No newline at end of file diff --git a/feeds/powershell.atom.xml.gz b/feeds/powershell.atom.xml.gz new file mode 100644 index 000000000..7d8e786f7 Binary files /dev/null and b/feeds/powershell.atom.xml.gz differ diff --git a/feeds/random.atom.xml b/feeds/random.atom.xml new file mode 100644 index 000000000..1e34eeded --- /dev/null +++ b/feeds/random.atom.xml @@ -0,0 +1,3 @@ + +Sipmann - Randomhttps://www.sipmann.com/2018-03-24T00:40:00-03:00Now posting on Grepora2018-03-24T00:40:00-03:002018-03-24T00:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-03-24:/now_posting_on_grepora.html<p>A few weeks ago I started posting at <a class="reference external" href="https://grepora.com/blog/">Grepora</a> blog. If you like or are looking for some Oracle related stuff, Grepora it's a good place to go and spend a time reading :). From time to time I'll be posting there, it doesn't mean that this blog will be closed …</p><p>A few weeks ago I started posting at <a class="reference external" href="https://grepora.com/blog/">Grepora</a> blog. If you like or are looking for some Oracle related stuff, Grepora it's a good place to go and spend a time reading :). From time to time I'll be posting there, it doesn't mean that this blog will be closed or anything like that, but probably this one will be more focused on Front-end stuff, a few tricks with linux and a lil less with Java.</p> + \ No newline at end of file diff --git a/feeds/random.atom.xml.gz b/feeds/random.atom.xml.gz new file mode 100644 index 000000000..75ffc4e9c Binary files /dev/null and b/feeds/random.atom.xml.gz differ diff --git a/feeds/sql-server.atom.xml b/feeds/sql-server.atom.xml new file mode 100644 index 000000000..2b51d7760 --- /dev/null +++ b/feeds/sql-server.atom.xml @@ -0,0 +1,184 @@ + +Sipmann - SQL Serverhttps://www.sipmann.com/2020-11-14T07:00:00-03:00Blocking a user on SQL Server based on a schedule2020-11-14T07:00:00-03:002020-11-14T07:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-11-14:/blocking-user-on-sql-server-based-on-schedule.html<p>Ok, some time ago, I've posted about how you can set limits to connections on SQL Server using the <a href="https://www.sipmann.com/limiting-connection-resources-sql-server.html#.X6Cz8IhKhPY">Resource Governor</a>. But what if you can't use it? You always can block logins using a login trigger, but I don't like the idea of having selects running on every login …</p><p>Ok, some time ago, I've posted about how you can set limits to connections on SQL Server using the <a href="https://www.sipmann.com/limiting-connection-resources-sql-server.html#.X6Cz8IhKhPY">Resource Governor</a>. But what if you can't use it? You always can block logins using a login trigger, but I don't like the idea of having selects running on every login. So I came across with a solution using a stored procedure, a table and the Agent.</p> +<p>The main idea is, store the time that a user must be blocked and using the Agent, disable or enable the user. Bellow you can see the table (the table is in Portuguese, but I have a few comment blocks to help you).</p> +<div class="highlight"><pre><span></span><code><span class="k">CREATE</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"> </span><span class="p">(</span><span class="w"></span> +<span class="w"> </span><span class="n">Id</span><span class="w"> </span><span class="nc">INT</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">LoginName</span><span class="w"> </span><span class="nc">NVARCHAR</span><span class="p">(</span><span class="mi">100</span><span class="p">)</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">HrInicio</span><span class="w"> </span><span class="nc">TIME</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"> </span><span class="cm">/* Startint block time */</span><span class="w"></span> +<span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="nc">TIME</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"> </span><span class="cm">/* Ending block time */</span><span class="w"></span> +<span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="nc">INT</span><span class="w"> </span><span class="k">DEFAULT</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="cm">/* 0 = unblocked, 1 = blocked */</span><span class="w"></span> +<span class="w"> </span><span class="k">PRIMARY</span><span class="w"> </span><span class="k">KEY</span><span class="w"> </span><span class="p">(</span><span class="n">Id</span><span class="p">)</span><span class="w"></span> +<span class="p">);</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> + +<span class="cm">/* Don&#39;t block the SA user, precautions, you know */</span><span class="w"></span> +<span class="k">ALTER</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"></span> +<span class="w"> </span><span class="k">ADD</span><span class="w"> </span><span class="k">CONSTRAINT</span><span class="w"> </span><span class="n">chk_users</span><span class="w"> </span><span class="k">CHECK</span><span class="w"> </span><span class="p">(</span><span class="n">LoginName</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;sa&#39;</span><span class="p">));</span><span class="w"></span> + +<span class="k">ALTER</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"></span> +<span class="w"> </span><span class="k">ADD</span><span class="w"> </span><span class="k">CONSTRAINT</span><span class="w"> </span><span class="n">chk_hora_final_maior</span><span class="w"> </span><span class="k">CHECK</span><span class="w"> </span><span class="p">(</span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="n">HrInicio</span><span class="p">);</span><span class="w"></span> + +<span class="k">ALTER</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"></span> +<span class="w"> </span><span class="k">ADD</span><span class="w"> </span><span class="k">CONSTRAINT</span><span class="w"> </span><span class="n">chk_status_bloqueio</span><span class="w"> </span><span class="k">CHECK</span><span class="w"> </span><span class="p">(</span><span class="n">Bloqueado</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">));</span><span class="w"></span> + +<span class="k">CREATE</span><span class="w"> </span><span class="k">SEQUENCE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">seq_HorariosBloqueio</span><span class="w"> </span><span class="k">START</span><span class="w"> </span><span class="k">WITH</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="n">INCREMENT</span><span class="w"> </span><span class="k">BY</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +</code></pre></div> + +<p>After creating the table, let's check the procedure that will handle the enabling/disabling the users. Be aware that on the procedure, I've set the database name where the table was stored, you can change it replacing the <code>DBATOOLS</code> text to the database name where you created the table.</p> +<div class="highlight"><pre><span></span><code><span class="k">IF</span><span class="w"> </span><span class="nf">OBJECT_ID</span><span class="p">(</span><span class="s1">&#39;dbo.sp_ValidarLogin&#39;</span><span class="p">)</span><span class="w"> </span><span class="k">IS</span><span class="w"> </span><span class="k">NULL</span><span class="w"></span> +<span class="w"> </span><span class="k">EXEC</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;CREATE PROCEDURE dbo.sp_ValidarLogin AS RETURN 0;&#39;</span><span class="p">);</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> + +<span class="k">CREATE</span><span class="w"> </span><span class="ow">OR</span><span class="w"> </span><span class="k">ALTER</span><span class="w"> </span><span class="k">PROC</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">sp_ValidarLogin</span><span class="w"></span> +<span class="k">AS</span><span class="w"> </span><span class="k">BEGIN</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="nc">NVARCHAR</span><span class="p">(</span><span class="mi">100</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="nc">TIME</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="k">SET</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nf">CAST</span><span class="p">(</span><span class="nf">GETDATE</span><span class="p">()</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="nc">TIME</span><span class="p">);</span><span class="w"></span> + +<span class="w"> </span><span class="cm">/* Block the ones that aren&#39;t blocked already and maches the time */</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="n">block_cursor</span><span class="w"> </span><span class="nc">CURSOR</span><span class="w"></span> +<span class="w"> </span><span class="k">FOR</span><span class="w"> </span><span class="k">SELECT</span><span class="w"> </span><span class="n">LoginName</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&lt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&gt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"></span> +<span class="w"> </span><span class="k">OPEN</span><span class="w"> </span><span class="n">block_cursor</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">block_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> + +<span class="w"> </span><span class="k">WHILE</span><span class="w"> </span><span class="nb">@@FETCH_STATUS</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"></span> +<span class="w"> </span><span class="k">BEGIN</span><span class="w"></span> +<span class="w"> </span><span class="k">exec</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;ALTER LOGIN &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="s1">&#39; DISABLE;&#39;</span><span class="p">);</span><span class="w"></span> + +<span class="w"> </span><span class="k">print</span><span class="w"> </span><span class="s1">&#39;Bloqued usuario &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">block_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> +<span class="w"> </span><span class="k">END</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">CLOSE</span><span class="w"> </span><span class="n">block_cursor</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="k">DEALLOCATE</span><span class="w"> </span><span class="n">block_cursor</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">UPDATE</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">SET</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&lt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&gt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"></span> + + +<span class="w"> </span><span class="cm">/* Enable up who was blocked */</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="nc">CURSOR</span><span class="w"></span> +<span class="w"> </span><span class="k">FOR</span><span class="w"> </span><span class="k">SELECT</span><span class="w"> </span><span class="n">LoginName</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="p">(</span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">OR</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="p">)</span><span class="w"></span> +<span class="w"> </span><span class="k">OPEN</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> + +<span class="w"> </span><span class="k">WHILE</span><span class="w"> </span><span class="nb">@@FETCH_STATUS</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"></span> +<span class="w"> </span><span class="k">BEGIN</span><span class="w"></span> +<span class="w"> </span><span class="k">exec</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;ALTER LOGIN &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"> </span><span class="o">+</span><span class="s1">&#39; ENABLE;&#39;</span><span class="p">);</span><span class="w"></span> + +<span class="w"> </span><span class="k">print</span><span class="w"> </span><span class="s1">&#39;Unbloqued usuario &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> +<span class="w"> </span><span class="k">END</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">CLOSE</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="k">DEALLOCATE</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">UPDATE</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">SET</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="p">(</span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">OR</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="p">)</span><span class="w"></span> +<span class="k">END</span><span class="p">;</span><span class="w"></span> +</code></pre></div> + +<p>Ok, so now all you have to do, is schedule a job to run that stored procedure from minute to minute. Again, the main idea is tell the procedure when a user must be blocked and when it'll be unblocked. </p> +<div class="highlight"><pre><span></span><code><span class="err"> -- Will block the user protheus from 10 AM till 15 PM</span> +<span class="err"> INSERT INTO dbo.HorariosBloqueio (Id, LoginName, HrInicio, HrTermino) VALUES (NEXT VALUE FOR seq_HorariosBloqueio, &#39;protheus&#39;, &#39;10:00:00&#39;, &#39;15:00:00&#39;);</span> +</code></pre></div>Removing a user from SQL Server database who owns a schema2019-09-06T07:00:00-03:002020-10-21T18:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2019-09-06:/removing-user-from-sql-server-database.html<p>Your customer urge you to drop a user from the MsSQL Server database, but you stuck with the following related error:</p> +<div class="highlight"><pre><span></span><code><span class="n">Error</span><span class="o">:</span> <span class="mi">15138</span> <span class="n">The</span> <span class="n">database</span> <span class="n">principal</span> <span class="n">owns</span> <span class="n">a</span> <span class="n">schema</span> <span class="k">in</span> <span class="n">the</span> <span class="n">database</span><span class="o">,</span> <span class="n">and</span> <span class="n">cannot</span> <span class="n">be</span> <span class="n">dropped</span><span class="o">.</span> +</code></pre></div> + +<p>That means that the user owns one or more shcemas of your database. If …</p><p>Your customer urge you to drop a user from the MsSQL Server database, but you stuck with the following related error:</p> +<div class="highlight"><pre><span></span><code><span class="n">Error</span><span class="o">:</span> <span class="mi">15138</span> <span class="n">The</span> <span class="n">database</span> <span class="n">principal</span> <span class="n">owns</span> <span class="n">a</span> <span class="n">schema</span> <span class="k">in</span> <span class="n">the</span> <span class="n">database</span><span class="o">,</span> <span class="n">and</span> <span class="n">cannot</span> <span class="n">be</span> <span class="n">dropped</span><span class="o">.</span> +</code></pre></div> + +<p>That means that the user owns one or more shcemas of your database. If you don't have access to the SSMS to see which schema or objects the user owns, the following SQL should do the job.</p> +<div class="highlight"><pre><span></span><code><span class="k">USE</span><span class="w"> </span><span class="o">[</span><span class="n">DATABASENAME</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> + +<span class="k">select</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Objeto</span><span class="p">,</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Owner</span><span class="w"></span> +<span class="k">from</span><span class="w"> </span><span class="n">sys</span><span class="p">.</span><span class="n">schemas</span><span class="w"> </span><span class="n">so</span><span class="w"></span> +<span class="k">inner</span><span class="w"> </span><span class="k">join</span><span class="w"> </span><span class="n">sysusers</span><span class="w"> </span><span class="n">su</span><span class="w"> </span><span class="k">on</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">principal_id</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">uid</span><span class="w"></span> +<span class="k">where</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">&#39;username&#39;</span><span class="w"></span> + +<span class="k">select</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Objeto</span><span class="p">,</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Owner</span><span class="p">,</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">xtype</span><span class="w"> </span><span class="n">Tipo</span><span class="w"></span> +<span class="k">from</span><span class="w"> </span><span class="n">sys</span><span class="p">.</span><span class="n">sysobjects</span><span class="w"> </span><span class="n">so</span><span class="w"></span> +<span class="k">inner</span><span class="w"> </span><span class="k">join</span><span class="w"> </span><span class="n">sysusers</span><span class="w"> </span><span class="n">su</span><span class="w"> </span><span class="k">on</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">uid</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">uid</span><span class="w"></span> +<span class="k">where</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">&#39;username&#39;</span><span class="w"></span> +</code></pre></div> + +<p>Once you have the objects/schemas owned by the user, you can change them with the following SQL (schema change sample):</p> +<div class="highlight"><pre><span></span><code><span class="k">USE</span><span class="w"> </span><span class="o">[</span><span class="n">DATABASENAME</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +<span class="k">ALTER</span><span class="w"> </span><span class="k">AUTHORIZATION</span><span class="w"> </span><span class="k">ON</span><span class="w"> </span><span class="k">SCHEMA</span><span class="o">::[</span><span class="n">db_datareader</span><span class="o">]</span><span class="w"> </span><span class="k">TO</span><span class="w"> </span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="w"> </span><span class="c1">-- new owner username</span> +<span class="k">ALTER</span><span class="w"> </span><span class="k">AUTHORIZATION</span><span class="w"> </span><span class="k">ON</span><span class="w"> </span><span class="k">SCHEMA</span><span class="o">::[</span><span class="n">db_datawriter</span><span class="o">]</span><span class="w"> </span><span class="k">TO</span><span class="w"> </span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +</code></pre></div> + +<p>Then you're ready to drop the user <code>DROP USER [username]</code></p> +<h2>How to list all the schemas and it's owners?</h2> +<p>Here's a script to list schemas and it's owners.</p> +<div class="highlight"><pre><span></span><code><span class="k">USE</span><span class="w"> </span><span class="o">[</span><span class="n">DATABASENAME</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +<span class="k">SELECT</span><span class="w"></span> +<span class="w"> </span><span class="nf">schema_name</span><span class="p">(</span><span class="nf">schema_id</span><span class="p">)</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="n">schemaname</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="nf">user_name</span><span class="p">(</span><span class="n">schm</span><span class="p">.</span><span class="n">principal_id</span><span class="p">)</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="n">username</span><span class="p">,</span><span class="w"> </span><span class="o">*</span><span class="w"></span> +<span class="k">FROM</span><span class="w"> </span><span class="n">sys</span><span class="p">.</span><span class="n">schemas</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="n">schm</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +</code></pre></div>Limiting Connection Resources on SQL Server2019-08-12T12:00:00-03:002019-08-12T12:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2019-08-12:/limiting-connection-resources-sql-server.html<p>Have you ever suffered from a slow SQLServer database? Someone love to run that heavy query in the database? Resource Governor to the rescue. You can set a few rules on how users (connections actually) will use the server/database resources based on a few things.</p> +<p>First things first, if …</p><p>Have you ever suffered from a slow SQLServer database? Someone love to run that heavy query in the database? Resource Governor to the rescue. You can set a few rules on how users (connections actually) will use the server/database resources based on a few things.</p> +<p>First things first, if you don't have DAC enabled, enable it now. Dealing with resource governor can lock you out of the database and leave you without action (almost... you can start the server with -c -m -f).</p> +<p>Now to understand how Resource Governor works, we have a few keywords <code>resource pool</code>, <code>workload group</code> e <code>Classifier Function</code>.</p> +<p><img alt="Pool Sample" src="/images/sql-pool.png"></p> +<h2>Resource Pool</h2> +<p>First, we have the Resource Pool, with is the bigger resource group that we have the ability to manage. With it, we can set a few things like: <code>MIN_CPU_PERCENT</code>, <code>MAX_CPU_PERCENT</code>, <code>MIN_MEMORY_PERCENT</code>, <code>MAX_MEMORY_PERCENT</code>, <code>MIN_IOPS_PER_VOLUME</code>, and <code>MAX_IOPS_PER_VOLUME</code>.</p> +<p>Be aware that the <code>MAX_CPU_PERCENT</code> will just "works" when there is another connection with a higher priority, otherwise it will use what is available. Let's create a pool.</p> +<div class="highlight"><pre><span></span><code><span class="k">CREATE</span><span class="w"> </span><span class="n">RESOURCE</span><span class="w"> </span><span class="n">POOL</span><span class="w"> </span><span class="o">[</span><span class="n">SpreadSheet</span><span class="o">]</span><span class="w"></span> +<span class="k">WITH</span><span class="w"> </span><span class="p">(</span><span class="w"></span> +<span class="w"> </span><span class="n">MIN_CPU_PERCENT</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">MAX_CPU_PERCENT</span><span class="o">=</span><span class="mi">20</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">MIN_MEMORY_PERCENT</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">MAX_MEMORY_PERCENT</span><span class="o">=</span><span class="mi">20</span><span class="w"></span> +<span class="p">);</span><span class="w"></span> +</code></pre></div> + +<p>## Workload Group</p> +<p>Then we have a workload group that "works" inside a pool, so you can have another granularity on how you can split your resources. Again, we have a few options: <code>IMPORTANCE</code>, <code>REQUEST_MAX_CPU_TIME_SEC</code>, <code>REQUEST_MAX_MEMORY_GRANT_PERCENT</code>, <code>GROUP_MAX_REQUESTS</code>.</p> +<p>The <code>IMPORTANCE</code> set guesses what... the importance of that workload inside the pool, you can set LOW, MEDIUM, HIGH. GROUP_MAX_REQUESTS sets how many requests can run at the same time inside that workload (0 will set as NO LIMIT)</p> +<div class="highlight"><pre><span></span><code><span class="k">CREATE</span><span class="w"> </span><span class="n">WORKLOAD</span><span class="w"> </span><span class="k">GROUP</span><span class="w"> </span><span class="o">[</span><span class="n">DepartmentA</span><span class="o">]</span><span class="w"> </span> +<span class="k">WITH</span><span class="w"> </span><span class="p">(</span><span class="w"></span> +<span class="w"> </span><span class="n">GROUP_MAX_REQUESTS</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">IMPORTANCE</span><span class="o">=</span><span class="n">LOW</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">REQUEST_MAX_CPU_TIME_SEC</span><span class="o">=</span><span class="mi">10</span><span class="p">,</span><span class="w"> </span><span class="c1">-- Time running/using CPU</span> +<span class="w"> </span><span class="n">REQUEST_MAX_MEMORY_GRANT_PERCENT</span><span class="o">=</span><span class="mi">15</span><span class="w"></span> +<span class="p">)</span><span class="w"> </span><span class="k">USING</span><span class="w"> </span><span class="o">[</span><span class="n">SpreadSheet</span><span class="o">]</span><span class="p">;</span><span class="w"> </span><span class="c1">-- pool name here</span> +</code></pre></div> + +<h2>Classifier Function</h2> +<p>This is where everything begins... This is the entry point where you should set the group name. It's a function that will run for every new connection so be aware that if your function runs lots of queries or some heavy stuff... that time will be added to the connection handshake. If the function returns NULL or a group name that doesn't exist, the 'default' group will be used... Yes, there is a default workload group where everything runs where there's no classifier.</p> +<div class="highlight"><pre><span></span><code><span class="k">CREATE</span><span class="w"> </span><span class="k">FUNCTION</span><span class="w"> </span><span class="n">fnClassWorkloadGovernor</span><span class="p">()</span><span class="w"> </span> +<span class="k">RETURNS</span><span class="w"> </span><span class="n">SYSNAME</span><span class="w"> </span><span class="k">WITH</span><span class="w"> </span><span class="n">SCHEMABINDING</span><span class="w"> </span> +<span class="k">AS</span><span class="w"> </span> +<span class="k">BEGIN</span><span class="w"> </span> +<span class="w"> </span><span class="k">IF</span><span class="w"> </span><span class="nf">APP_NAME</span><span class="p">()</span><span class="w"> </span><span class="ow">LIKE</span><span class="w"> </span><span class="s1">&#39;%Excel%&#39;</span><span class="w"></span> +<span class="w"> </span><span class="k">RETURN</span><span class="w"> </span><span class="s1">&#39;DepartmentA&#39;</span><span class="w"></span> + +<span class="w"> </span><span class="k">IF</span><span class="w"> </span><span class="nf">HOST_NAME</span><span class="p">()</span><span class="w"> </span><span class="ow">LIKE</span><span class="w"> </span><span class="s1">&#39;%THAT_MACHINE_OR_APP_SERVER%&#39;</span><span class="w"></span> +<span class="w"> </span><span class="k">RETURN</span><span class="w"> </span><span class="s1">&#39;LowPriority&#39;</span><span class="w"></span> + +<span class="w"> </span><span class="k">RETURN</span><span class="w"> </span><span class="k">NULL</span><span class="w"></span> +<span class="k">END</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> + +<span class="k">ALTER</span><span class="w"> </span><span class="n">RESOURCE</span><span class="w"> </span><span class="n">GOVERNOR</span><span class="w"> </span><span class="k">WITH</span><span class="w"> </span><span class="p">(</span><span class="n">CLASSIFIER_FUNCTION</span><span class="o">=</span><span class="n">dbo</span><span class="p">.</span><span class="n">fnClassWorkloadGovernor</span><span class="p">);</span><span class="w"></span> +<span class="k">ALTER</span><span class="w"> </span><span class="n">RESOURCE</span><span class="w"> </span><span class="n">GOVERNOR</span><span class="w"> </span><span class="k">RECONFIGURE</span><span class="p">;</span><span class="w"></span> +</code></pre></div> + +<p>There you go... now you have a fully working resource governor, but look out that If you want to delete that classifier function, first you have to remove it from the resource governor (look the SCHEMABINDING at the create up there).</p> +<p>To disable Resource Governor</p> +<div class="highlight"><pre><span></span><code><span class="k">ALTER</span><span class="w"> </span><span class="n">RESOURCE</span><span class="w"> </span><span class="n">GOVERNOR</span><span class="w"> </span><span class="k">WITH</span><span class="w"> </span><span class="p">(</span><span class="n">CLASSIFIER_FUNCTION</span><span class="o">=</span><span class="k">null</span><span class="p">)</span><span class="w"></span> +<span class="k">ALTER</span><span class="w"> </span><span class="n">RESOURCE</span><span class="w"> </span><span class="n">GOVERNOR</span><span class="w"> </span><span class="k">RECONFIGURE</span><span class="w"></span> + +<span class="k">ALTER</span><span class="w"> </span><span class="n">RESOURCE</span><span class="w"> </span><span class="n">GOVERNOR</span><span class="w"> </span><span class="n">DISABLE</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +</code></pre></div> \ No newline at end of file diff --git a/feeds/sql-server.atom.xml.gz b/feeds/sql-server.atom.xml.gz new file mode 100644 index 000000000..4e54fce9e Binary files /dev/null and b/feeds/sql-server.atom.xml.gz differ diff --git a/feeds/tools.atom.xml b/feeds/tools.atom.xml new file mode 100644 index 000000000..0ffd3f5c7 --- /dev/null +++ b/feeds/tools.atom.xml @@ -0,0 +1,10 @@ + +Sipmann - Toolshttps://www.sipmann.com/2020-12-02T14:00:00-03:00Apache Nifi JSON to SQL Replacing underscore2020-12-02T14:00:00-03:002020-12-02T14:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-12-02:/apache-nifi-json-to-sql-replacing-underscore.html<p>Recently I was doing some ETL with Apache NiFi. But after a few minutes of drawing my flow, I saw that the component ConvertJSONToSQL was replacing the underscore ('_') from the field name in the where condition (I was preparing an Update SQL). That was weird because, at the set …</p><p>Recently I was doing some ETL with Apache NiFi. But after a few minutes of drawing my flow, I saw that the component ConvertJSONToSQL was replacing the underscore ('_') from the field name in the where condition (I was preparing an Update SQL). That was weird because, at the set statement, the field name was kept intact. After some research, I found that the property (see bellow) <code>Translate Field Names</code> was responsible for that weird replacement.</p> +<p><img alt="Apache NiFi JSONToSQL config" src="/images/apache_nifi_jsontosql.png"></p> +<p>Before setting it to <strong>FALSE</strong>, be aware that the properties on your JSON data must match exactly the name of your fields.</p>Using git hooks to easy your life2019-07-30T20:00:00-03:002019-07-30T20:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2019-07-30:/using_git_hooks_easy_your_life.html<p>Hey folks, it's been a time since my last post. In the meantime, I moved to another state, changed job, and started learning new kinds of stuff. Today I would like to share one thing that I usually do with my small git projects. Git has many cool features, git …</p><p>Hey folks, it's been a time since my last post. In the meantime, I moved to another state, changed job, and started learning new kinds of stuff. Today I would like to share one thing that I usually do with my small git projects. Git has many cool features, git hooks were one of them. I'll talk about the pre-commit hook today.</p> +<p>Let's say that, for some reason, you don't have a CI tool/server running after every commit and you want to enforce that every developer runs the tests before every commit? Git pre-commit to the rescue. You can code the hooks with shell, ruby, python, and I could be wrong, but even PHP would work. pre-commit is a client-side hook (we have server side too) and he's located inside the <cite>.git/hooks</cite> folder. Let's jump to the code... Create a file called 'pre-commit' inside that folder with the following code.</p> +<div class="highlight"><pre><span></span><span class="ch">#!/bin/bash</span> +npm <span class="nb">test</span> <span class="c1"># assuming you&#39;re using it inside a nodeJS project</span> +</pre></div> +<p>Don't forget to make the script executable!! Now break your test and try to commit. That's easy but can save you from breaking the tests at the main CI/Travis/Codeship/etc and being notified by email :). Why not even validate the lint of your project or check if the coverage doesn't fall? Does your team/company have a patter for commit messages? No problem, there is a hook called <cite>commit-msg</cite> that you can use to validate your message.</p> + \ No newline at end of file diff --git a/feeds/tools.atom.xml.gz b/feeds/tools.atom.xml.gz new file mode 100644 index 000000000..08b617c69 Binary files /dev/null and b/feeds/tools.atom.xml.gz differ diff --git a/flutter_with_firebase_auth_crashing.html b/flutter_with_firebase_auth_crashing.html new file mode 100644 index 000000000..4cda043cb --- /dev/null +++ b/flutter_with_firebase_auth_crashing.html @@ -0,0 +1,433 @@ + + + + + + + + Flutter + firebase auth crashing - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Flutter + firebase auth crashing

+
+ +
+
+ +
+

Hey Folks, recently I've started learning Flutter and right after a TODO List, I tried a Firebase integration. But as soon as I started setting the dependencies, my app stopped opening... just a crash. After a few logs digging, I've found the following log.

+
AndroidRuntime: FATAL EXCEPTION: main
+AndroidRuntime: Process: com.example.diadocasal, PID: 13672
+AndroidRuntime: java.lang.NoClassDefFoundError: Failed resolution of: Landroid/support/v4/util/ArrayMap;
+AndroidRuntime:     at com.google.android.gms.internal.measurement.zzca.<clinit>(Unknown Source:60)
+AndroidRuntime:     at com.google.android.gms.internal.measurement.zzcm.zzr(Unknown Source:7)
+AndroidRuntime:     at com.google.android.gms.measurement.internal.zzfj.<init>(Unknown Source:23)
+
+ +

Notice the "NoClassDefFound" of an ArrayMap. To solve that I did the following changes to the files:

+
//build.gradle file
+ ext.kotlin_version = '1.3.20'
+[...]
+ dependencies {
+        classpath 'com.android.tools.build:gradle:3.3.0' // gradle version
+
+ +
;gradle.properties file
+org.gradle.jvmargs=-Xmx1536M ;mine have just this line at first
+android.useAndroidX=true ; uses androidX instead of the default support library
+android.enableJetifier=true ; uses jetpack libraries
+android.enableR8=true ; the new code shriker
+
+ +

After that, voilà, app up and running.

+
+ + +
+
+

Translations:

+
    +
+
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/flutter_with_firebase_auth_crashing.html.gz b/flutter_with_firebase_auth_crashing.html.gz new file mode 100644 index 000000000..2f7a9d747 Binary files /dev/null and b/flutter_with_firebase_auth_crashing.html.gz differ diff --git a/images/Resultado.PNG b/images/Resultado.PNG new file mode 100644 index 000000000..f1e5147de Binary files /dev/null and b/images/Resultado.PNG differ diff --git a/images/Resultado.PNG.gz b/images/Resultado.PNG.gz new file mode 100644 index 000000000..009bf3860 Binary files /dev/null and b/images/Resultado.PNG.gz differ diff --git a/images/admin_modificado.png b/images/admin_modificado.png new file mode 100644 index 000000000..afd6cf2d7 Binary files /dev/null and b/images/admin_modificado.png differ diff --git a/images/apache_nifi_jsontosql.png b/images/apache_nifi_jsontosql.png new file mode 100644 index 000000000..11f83a583 Binary files /dev/null and b/images/apache_nifi_jsontosql.png differ diff --git a/images/app_inicial.png b/images/app_inicial.png new file mode 100644 index 000000000..f6fd25008 Binary files /dev/null and b/images/app_inicial.png differ diff --git a/images/app_visual_1.png b/images/app_visual_1.png new file mode 100644 index 000000000..68de30d21 Binary files /dev/null and b/images/app_visual_1.png differ diff --git a/images/azure-data-fundamentals-600x600.png b/images/azure-data-fundamentals-600x600.png new file mode 100644 index 000000000..88cf15c7b Binary files /dev/null and b/images/azure-data-fundamentals-600x600.png differ diff --git a/images/azure_certification.png b/images/azure_certification.png new file mode 100644 index 000000000..01d81af00 Binary files /dev/null and b/images/azure_certification.png differ diff --git a/images/azure_functions.gif b/images/azure_functions.gif new file mode 100644 index 000000000..6bf5fa11f Binary files /dev/null and b/images/azure_functions.gif differ diff --git a/images/azure_monitoring.png b/images/azure_monitoring.png new file mode 100644 index 000000000..3471441a3 Binary files /dev/null and b/images/azure_monitoring.png differ diff --git a/images/block_sql_server_user.png b/images/block_sql_server_user.png new file mode 100644 index 000000000..f146628d7 Binary files /dev/null and b/images/block_sql_server_user.png differ diff --git a/images/bug.png b/images/bug.png new file mode 100644 index 000000000..697400855 Binary files /dev/null and b/images/bug.png differ diff --git a/images/csharp_toplevel.png b/images/csharp_toplevel.png new file mode 100644 index 000000000..7dabb89cf Binary files /dev/null and b/images/csharp_toplevel.png differ diff --git a/images/deletar_mysql_monitorin_powershell.png b/images/deletar_mysql_monitorin_powershell.png new file mode 100644 index 000000000..8ce9f18dc Binary files /dev/null and b/images/deletar_mysql_monitorin_powershell.png differ diff --git a/images/deletar_mysql_monitoring_restart.png b/images/deletar_mysql_monitoring_restart.png new file mode 100644 index 000000000..7713c6a0a Binary files /dev/null and b/images/deletar_mysql_monitoring_restart.png differ diff --git a/images/deletar_powershell.png b/images/deletar_powershell.png new file mode 100644 index 000000000..e73b73161 Binary files /dev/null and b/images/deletar_powershell.png differ diff --git a/images/ef_core_allcolumns.png b/images/ef_core_allcolumns.png new file mode 100644 index 000000000..ba2483af0 Binary files /dev/null and b/images/ef_core_allcolumns.png differ diff --git a/images/ef_core_less_columns.png b/images/ef_core_less_columns.png new file mode 100644 index 000000000..1b7f3b3b1 Binary files /dev/null and b/images/ef_core_less_columns.png differ diff --git a/images/efcore_select_fields.png b/images/efcore_select_fields.png new file mode 100644 index 000000000..3badbd691 Binary files /dev/null and b/images/efcore_select_fields.png differ diff --git a/images/header.jpg b/images/header.jpg new file mode 100644 index 000000000..fffbdc87f Binary files /dev/null and b/images/header.jpg differ diff --git a/images/header.webp b/images/header.webp new file mode 100644 index 000000000..74f11bbe0 Binary files /dev/null and b/images/header.webp differ diff --git a/images/header.webp.new b/images/header.webp.new new file mode 100644 index 000000000..2b9346014 Binary files /dev/null and b/images/header.webp.new differ diff --git a/images/header.webp.new.gz b/images/header.webp.new.gz new file mode 100644 index 000000000..7b34ca3da Binary files /dev/null and b/images/header.webp.new.gz differ diff --git a/images/icons/chart-pie-solid.svg b/images/icons/chart-pie-solid.svg new file mode 100644 index 000000000..97f83f834 --- /dev/null +++ b/images/icons/chart-pie-solid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/icons/chart-pie-solid.svg.gz b/images/icons/chart-pie-solid.svg.gz new file mode 100644 index 000000000..d51548a5a Binary files /dev/null and b/images/icons/chart-pie-solid.svg.gz differ diff --git a/images/icons/cloud-solid.svg b/images/icons/cloud-solid.svg new file mode 100644 index 000000000..113f89753 --- /dev/null +++ b/images/icons/cloud-solid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/icons/cloud-solid.svg.gz b/images/icons/cloud-solid.svg.gz new file mode 100644 index 000000000..262a466de Binary files /dev/null and b/images/icons/cloud-solid.svg.gz differ diff --git a/images/icons/database-solid.svg b/images/icons/database-solid.svg new file mode 100644 index 000000000..4b87f7fac --- /dev/null +++ b/images/icons/database-solid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/icons/database-solid.svg.gz b/images/icons/database-solid.svg.gz new file mode 100644 index 000000000..d139d086b Binary files /dev/null and b/images/icons/database-solid.svg.gz differ diff --git a/images/menu_apps.png b/images/menu_apps.png new file mode 100644 index 000000000..643cef72a Binary files /dev/null and b/images/menu_apps.png differ diff --git a/images/microservice_postman.png b/images/microservice_postman.png new file mode 100644 index 000000000..63bd0e299 Binary files /dev/null and b/images/microservice_postman.png differ diff --git a/images/microservices_rabit_pt1.png b/images/microservices_rabit_pt1.png new file mode 100644 index 000000000..85a8928a6 Binary files /dev/null and b/images/microservices_rabit_pt1.png differ diff --git a/images/mysql_dual_password.png b/images/mysql_dual_password.png new file mode 100644 index 000000000..495345027 Binary files /dev/null and b/images/mysql_dual_password.png differ diff --git a/images/mysql_monitorin_powershell.webp b/images/mysql_monitorin_powershell.webp new file mode 100644 index 000000000..8b4851499 Binary files /dev/null and b/images/mysql_monitorin_powershell.webp differ diff --git a/images/mysql_monitoring_restart.webp b/images/mysql_monitoring_restart.webp new file mode 100644 index 000000000..bd5da5855 Binary files /dev/null and b/images/mysql_monitoring_restart.webp differ diff --git a/images/og/java-wildfly.png b/images/og/java-wildfly.png new file mode 100644 index 000000000..79e41e88d Binary files /dev/null and b/images/og/java-wildfly.png differ diff --git a/images/og/mysql-permission.png b/images/og/mysql-permission.png new file mode 100644 index 000000000..b629f28c7 Binary files /dev/null and b/images/og/mysql-permission.png differ diff --git a/images/og/yo-reac-gen.png b/images/og/yo-reac-gen.png new file mode 100644 index 000000000..d18030e85 Binary files /dev/null and b/images/og/yo-reac-gen.png differ diff --git a/images/owner.PNG b/images/owner.PNG new file mode 100644 index 000000000..bc9401ff4 Binary files /dev/null and b/images/owner.PNG differ diff --git a/images/owner.PNG.gz b/images/owner.PNG.gz new file mode 100644 index 000000000..61d16e3f1 Binary files /dev/null and b/images/owner.PNG.gz differ diff --git a/images/powershell.webp b/images/powershell.webp new file mode 100644 index 000000000..d4a2d0831 Binary files /dev/null and b/images/powershell.webp differ diff --git a/images/rabbitmq.png b/images/rabbitmq.png new file mode 100644 index 000000000..a7ed1a2d7 Binary files /dev/null and b/images/rabbitmq.png differ diff --git a/images/sipmann.com.png b/images/sipmann.com.png new file mode 100644 index 000000000..d44e334f4 Binary files /dev/null and b/images/sipmann.com.png differ diff --git a/images/sql-pool.png b/images/sql-pool.png new file mode 100644 index 000000000..3143c6959 Binary files /dev/null and b/images/sql-pool.png differ diff --git a/images/zabbix_cache_filling.png b/images/zabbix_cache_filling.png new file mode 100644 index 000000000..92bbda7c8 Binary files /dev/null and b/images/zabbix_cache_filling.png differ diff --git a/images/zabbix_low_memory.png b/images/zabbix_low_memory.png new file mode 100644 index 000000000..0fef154dc Binary files /dev/null and b/images/zabbix_low_memory.png differ diff --git a/images/zabbix_low_memory_mode.png b/images/zabbix_low_memory_mode.png new file mode 100644 index 000000000..b7ca5581f Binary files /dev/null and b/images/zabbix_low_memory_mode.png differ diff --git a/images/zabbix_low_memory_solved.png b/images/zabbix_low_memory_solved.png new file mode 100644 index 000000000..f76ee7420 Binary files /dev/null and b/images/zabbix_low_memory_solved.png differ diff --git a/images/zabbix_pinger01.png b/images/zabbix_pinger01.png new file mode 100644 index 000000000..4db4398c0 Binary files /dev/null and b/images/zabbix_pinger01.png differ diff --git a/images/zabbix_pooler.png b/images/zabbix_pooler.png new file mode 100644 index 000000000..3667b0316 Binary files /dev/null and b/images/zabbix_pooler.png differ diff --git a/images/zabbix_pooler_3.png b/images/zabbix_pooler_3.png new file mode 100644 index 000000000..1869efb15 Binary files /dev/null and b/images/zabbix_pooler_3.png differ diff --git a/images/zabbix_pooler_4.png b/images/zabbix_pooler_4.png new file mode 100644 index 000000000..4646b7c1f Binary files /dev/null and b/images/zabbix_pooler_4.png differ diff --git a/index.html b/index.html new file mode 100644 index 000000000..6671b42d0 --- /dev/null +++ b/index.html @@ -0,0 +1,603 @@ + + + + + + + + Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+ +
+
+
+

Apache Nifi JSON to SQL Replacing underscore

+
+ +
+
+ +
+

Recently I was doing some ETL with Apache NiFi. But after a few minutes of drawing my flow, I saw that the component ConvertJSONToSQL was replacing the underscore ('_') from the field name in the where condition (I was preparing an Update SQL). That was weird because, at the set …

+
+ + + +
+
+
+
+ +
+
+ + + + + + + +
+

So, you use Entity Framework Core, and you usually code your selects like the following, maybe you are getting too much data.

+
var products = Products
+    .Where(p => p.UnitsInStock > 0)
+    .OrderBy(p => p.ProductName)
+    .ToList()
+
+ +

Running the query above, on my table, you'll get the following output, take a look …

+
+ + + +
+
+
+
+
+ + + + + +
+

Zabbix Running on Low Memory Mode

+
+ +
+
+ +
+

Hey folks, another Zabbix post today. This one it's about increasing the Zabbix Server Cache. It's pretty common (if you have the default settings only) get a warning about your Zabbix value cache running on low memory mode at your dashboard or logs.

+

Zabbix Dashboard warning about the memory problem +Zabbix Dashboard cache graph 70% used

+

To solve, go back to your Zabbix …

+
+ + + +
+
+
+
+
+ + + + + + + +
+

I've been migration some bash scripts that I have to PowerShell, and it's time to migrate a script that monitors the replication of a MySQL database. The credit for the original script goes to Paweł. It's a simple script where I seek a few tags/fields that we get from …

+
+ + + +
+
+
+
+
+
+

Microsoft Against Covid

+
+ +
+
+ +
+

Has your job been affected by covid? Well, last week I've posted on Grepora about a Free Certification Voucher that Microsoft was giving away at the Microsoft Ignite event. After that, I found that they were also giving a huge discount to people who have had their job affected by …

+
+ + + +
+
+
+
+
+ + + + + +
+

The power of PowerShell

+
+ +
+
+ +
+

As a long time Linux user, I've automated a few things with bash scripts and stayed away from PowerShell... I've moved to a Windows environment a few years ago and still, haven gave a shot to PS. But why not? I've made a few scripts to automate some tasks at …

+
+ + + +
+
+
+
+
+ + + + + +
+

Top Level Statement in C# 9

+
+ +
+
+ +
+

Hey folks, I'm coming along to tell you a few things about the new feature of C# 9. Every time you want to start a new project, you always have the same Main File, with the same structure. At the next version of C# (version 9), we'll have a new …

+
+ + + +
+
+
+
+
+ + 1 + 2 + 3 + » + +
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/index.html.gz b/index.html.gz new file mode 100644 index 000000000..3e5460667 Binary files /dev/null and b/index.html.gz differ diff --git a/index2.html b/index2.html new file mode 100644 index 000000000..f937a5682 --- /dev/null +++ b/index2.html @@ -0,0 +1,582 @@ + + + + + + + + Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Zabbix poller processes more than 75%

+
+ +
+
+ +
+

Hey folks, this is the third post about tweaking the Zabbix configurations. All changes that I've suggested here were based on a Zabbix Server with 50+ hosts. Another thing that can happen to your server, it's the poller get overwhelmed by the amount of servers that need to be polled …

+
+ + + +
+
+
+
+
+ + + + + + + +
+

Sometimes you get your self in need to monitor a website's health or it's content for changes. Of course, there's plenty of options out there, but for the sake of curiosity, let's code our own to see what we can do. First things first. Everything you'll see here, you can …

+
+ + + +
+
+
+
+
+ + + + + + + +
+

Hey folks, if you want to achieve some certification this year, keep an eye open for vouchers. A few months ago, Oracle released a set of free courses with certifications. Now it's Microsoft time. Microsoft is updating they're certifications and we have a voucher of 80% discount using the coupon …

+
+ + + +
+
+
+
+
+
+

Zabbix ICMP pinger processes more than 75%

+
+ +
+
+ +
+

So your monitoring sytems have grown and your zabbix started loggin "Zabbix icmp pinger processes more than 75% busy" at the dashboard.

+

Dashboard do zabbix avisando sobre o erro

+

All you have to do is open your config file (/etc/zabbix/zabbix_server.conf) and find the a tag named StartPingers. It'll be commented by default. Uncomment it …

+
+ + + +
+
+
+
+
+
+

Zabbix Server Out of Memory

+
+ +
+
+ +
+

Do you have a crashing Zabbix Server and looking through the log /var/log/zabbix/zabbix_server.log you see the following out of memory message?

+
__mem_malloc: skipped 0 asked 24 skip_min 18446744073709551615 skip_max 0
+[file:dbconfig.c,line:94] __zbx_mem_realloc(): out of memory (requested 16 bytes)
+[file:dbconfig.c,line …

+
+ + + +
+
+
+
+
+
+

Flutter + firebase auth crashing

+
+ +
+
+ +
+

Hey Folks, recently I've started learning Flutter and right after a TODO List, I tried a Firebase integration. But as soon as I started setting the dependencies, my app stopped opening... just a crash. After a few logs digging, I've found the following log.

+
AndroidRuntime: FATAL EXCEPTION: main
+AndroidRuntime: Process …

+
+ + + +
+
+
+
+
+ + +
+

Your customer urge you to drop a user from the MsSQL Server database, but you stuck with the following related error:

+
Error: 15138 The database principal owns a schema in the database, and cannot be dropped.
+
+ +

That means that the user owns one or more shcemas of your database. If …

+
+ + + +
+
+
+
+
+ + + + + +
+

Limiting Connection Resources on SQL Server

+
+ +
+
+ +
+

Have you ever suffered from a slow SQLServer database? Someone love to run that heavy query in the database? Resource Governor to the rescue. You can set a few rules on how users (connections actually) will use the server/database resources based on a few things.

+

First things first, if …

+
+ + + +
+
+
+
+
+
+

Using git hooks to easy your life

+
+ +
+
+ +
+

Hey folks, it's been a time since my last post. In the meantime, I moved to another state, changed job, and started learning new kinds of stuff. Today I would like to share one thing that I usually do with my small git projects. Git has many cool features, git …

+
+ + + +
+
+
+
+ +
+
+ « + + 1 + 2 + 3 + » + +
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/index2.html.gz b/index2.html.gz new file mode 100644 index 000000000..8544103b0 Binary files /dev/null and b/index2.html.gz differ diff --git a/index3.html b/index3.html new file mode 100644 index 000000000..31c73e4a7 --- /dev/null +++ b/index3.html @@ -0,0 +1,526 @@ + + + + + + + + Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+ + + + + + + +
+

This is the first part of a microservices development series. The service will consist of the bellow architecture, where we will expose an image optimizer service that will forward the request to a RabbitMQ queue and answer with the bytecode of the optimized image. It shouldn't be a long series …

+
+ + + +
+
+
+
+
+
+

Connecting to a database through SSH

+
+ +
+
+ +
+

If someday, for some reason, you need to establish a connection with a database which is behind a firewall and you only have SSH access on that server (and you don't want to use a CLI) you can do an SSH tunnel. It's pretty simple, bellow has a sample of …

+
+ + + +
+
+
+
+
+
+

Now posting on Grepora

+
+ +
+
+ +
+

A few weeks ago I started posting at Grepora blog. If you like or are looking for some Oracle related stuff, Grepora it's a good place to go and spend a time reading :). From time to time I'll be posting there, it doesn't mean that this blog will be closed …

+
+ + + +
+
+
+
+
+ + + + + + + +
+

Since Parcel JS arrived, I've been using it a lot as an awesome alternative for WebPack. Webpack isn't bad but IMO it's too complex for the job and parcel do the same (at least the basic) with almost zero configuration. But if you need to create many apps (like a …

+
+ + + +
+
+
+
+
+ + + + + + + +
+

Last day I decided to deploy a MySQL Docker image to work with my Java application. I've been using PostgreSQL instead and have no problems at all, but after I moved to MySQL, the app didn't connect anymore with the database and throw some "Could not open connection" at my …

+
+ + + +
+
+
+
+ +
+
+ + + + + +
+

Change display settings on linux with Disper

+
+ +
+
+ +
+

From time to time, I change the Linux distro on my laptop or just do a fresh install on it. And once in a while, have random problems with external displays. It can be something really "simple" like don't detecting the external monitor or something crazy like the image below …

+
+ + + +
+
+
+
+
+
+

Java - Files.readAllBytes throws OutOfMemory

+
+ +
+
+ +
+

When you need to interact with files, there's the possibility to read all bytes from the file with Files.readAllBytes. But be aware of the kinds of files your application will deal with because the Java API files have a limit for the buffer that is defined as Integer.MAX_VALUE …

+
+ + + +
+
+
+
+
+ « + + 1 + 2 + 3 + +
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/index3.html.gz b/index3.html.gz new file mode 100644 index 000000000..c32e04ef8 Binary files /dev/null and b/index3.html.gz differ diff --git a/limiting-connection-resources-sql-server.html b/limiting-connection-resources-sql-server.html new file mode 100644 index 000000000..4d2dc595d --- /dev/null +++ b/limiting-connection-resources-sql-server.html @@ -0,0 +1,532 @@ + + + + + + + + Limiting Connection Resources on SQL Server - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Limiting Connection Resources on SQL Server

+
+ +
+
+ +
+

Have you ever suffered from a slow SQLServer database? Someone love to run that heavy query in the database? Resource Governor to the rescue. You can set a few rules on how users (connections actually) will use the server/database resources based on a few things.

+

First things first, if you don't have DAC enabled, enable it now. Dealing with resource governor can lock you out of the database and leave you without action (almost... you can start the server with -c -m -f).

+

Now to understand how Resource Governor works, we have a few keywords resource pool, workload group e Classifier Function.

+

Pool Sample

+

Resource Pool

+

First, we have the Resource Pool, with is the bigger resource group that we have the ability to manage. With it, we can set a few things like: MIN_CPU_PERCENT, MAX_CPU_PERCENT, MIN_MEMORY_PERCENT, MAX_MEMORY_PERCENT, MIN_IOPS_PER_VOLUME, and MAX_IOPS_PER_VOLUME.

+

Be aware that the MAX_CPU_PERCENT will just "works" when there is another connection with a higher priority, otherwise it will use what is available. Let's create a pool.

+
CREATE RESOURCE POOL [SpreadSheet]
+WITH (
+    MIN_CPU_PERCENT=0,
+    MAX_CPU_PERCENT=20,
+    MIN_MEMORY_PERCENT=0,
+    MAX_MEMORY_PERCENT=20
+);
+
+ +

## Workload Group

+

Then we have a workload group that "works" inside a pool, so you can have another granularity on how you can split your resources. Again, we have a few options: IMPORTANCE, REQUEST_MAX_CPU_TIME_SEC, REQUEST_MAX_MEMORY_GRANT_PERCENT, GROUP_MAX_REQUESTS.

+

The IMPORTANCE set guesses what... the importance of that workload inside the pool, you can set LOW, MEDIUM, HIGH. GROUP_MAX_REQUESTS sets how many requests can run at the same time inside that workload (0 will set as NO LIMIT)

+
CREATE WORKLOAD GROUP [DepartmentA] 
+WITH (
+    GROUP_MAX_REQUESTS=2,
+    IMPORTANCE=LOW,
+    REQUEST_MAX_CPU_TIME_SEC=10, -- Time running/using CPU
+    REQUEST_MAX_MEMORY_GRANT_PERCENT=15
+) USING [SpreadSheet]; -- pool name here
+
+ +

Classifier Function

+

This is where everything begins... This is the entry point where you should set the group name. It's a function that will run for every new connection so be aware that if your function runs lots of queries or some heavy stuff... that time will be added to the connection handshake. If the function returns NULL or a group name that doesn't exist, the 'default' group will be used... Yes, there is a default workload group where everything runs where there's no classifier.

+
CREATE FUNCTION fnClassWorkloadGovernor() 
+RETURNS SYSNAME WITH SCHEMABINDING 
+AS 
+BEGIN 
+    IF APP_NAME() LIKE '%Excel%'
+        RETURN 'DepartmentA'
+
+    IF HOST_NAME() LIKE '%THAT_MACHINE_OR_APP_SERVER%'
+        RETURN 'LowPriority'
+
+    RETURN NULL
+END
+GO
+
+ALTER RESOURCE GOVERNOR WITH (CLASSIFIER_FUNCTION=dbo.fnClassWorkloadGovernor);
+ALTER RESOURCE GOVERNOR RECONFIGURE;
+
+ +

There you go... now you have a fully working resource governor, but look out that If you want to delete that classifier function, first you have to remove it from the resource governor (look the SCHEMABINDING at the create up there).

+

To disable Resource Governor

+
ALTER RESOURCE GOVERNOR WITH (CLASSIFIER_FUNCTION=null)
+ALTER RESOURCE GOVERNOR RECONFIGURE
+
+ALTER RESOURCE GOVERNOR DISABLE
+GO
+

+
+ + +
+
+

Translations:

+
    +
+
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/limiting-connection-resources-sql-server.html.gz b/limiting-connection-resources-sql-server.html.gz new file mode 100644 index 000000000..8901207b1 Binary files /dev/null and b/limiting-connection-resources-sql-server.html.gz differ diff --git a/linux-external-display-with-disper.html b/linux-external-display-with-disper.html new file mode 100644 index 000000000..6cc73bcef --- /dev/null +++ b/linux-external-display-with-disper.html @@ -0,0 +1,420 @@ + + + + + + + + Change display settings on linux with Disper - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Change display settings on linux with Disper

+
+ +
+
+ +
+

From time to time, I change the Linux distro on my laptop or just do a fresh install on it. And once in a while, have random problems with external displays. It can be something really "simple" like don't detecting the external monitor or something crazy like the image below.

+Display bug +

As you can see at the image, the mint detected the display but mirrored it in a crazy way that works but doesn't at the same time. If you try anything and doesn't get working, or just wanna skip the whole job of configuring complexes text files, give a try to Disper. Download the latest version. +Extract it on any folder, and make install it (on the extracted folder).

+
make install
+
+

After that, you can start using it... There are a few options that will serve you well.

+
disper -e #extend your display
+
+
disper -c #clone your display
+
+
disper -s #only your external display
+
+

+
+ + +
+
+

Translations:

+
    +
+
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/linux-external-display-with-disper.html.gz b/linux-external-display-with-disper.html.gz new file mode 100644 index 000000000..fb1c3c084 Binary files /dev/null and b/linux-external-display-with-disper.html.gz differ diff --git a/microservices_nodejs_express_rabbitmq_part_1.html b/microservices_nodejs_express_rabbitmq_part_1.html new file mode 100644 index 000000000..02954de6b --- /dev/null +++ b/microservices_nodejs_express_rabbitmq_part_1.html @@ -0,0 +1,548 @@ + + + + + + + + Microservices with NodeJS, Express.js and RabbitMQ Part 1 - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+ + +
+

This is the first part of a microservices development series. The service will consist of the bellow architecture, where we will expose an image optimizer service that will forward the request to a RabbitMQ queue and answer with the bytecode of the optimized image. It shouldn't be a long series so let's see what we can do.

+Service architecture +

Let's get our environment working. First, we'll need to install the libraries that we'll use.

+

Create a dir and initialize the nodejs application inside it (npm init) and then let's install the deps.

+
    +
  • amqplib - AMQP lib to interact with rabbitmq
  • +
  • express - Do our basic rest API
  • +
  • express-fileupload - easy file upload parser
  • +
  • imagemin and imagemin-pngquant - our image compacter
  • +
+
npm install --save express amqplib express-fileupload imagemin imagemin-pngquant
+
+

Now let's write the entry points for our service, we'll have two basic entry points. The path / that will have a welcome message, the second path will be /upload and this is the one that will handle the image and produce a job for our workers.

+
const express = require('express');
+const fileUpload = require('express-fileupload');
+
+//Instantiate the app and set the fileupload parser to manage files
+const app = express();
+app.use(fileUpload());
+
+//Our index entry point
+app.get('/', (req, res) => res.send('Hello From ImageCompacter service'));
+
+//The path that will handle the image file and throw them to the queue
+app.post('/upload', (req, res) => {
+    //With express-fileupload we can grab the files like this
+    let img = req.files.image; //"image" is the name of the input
+
+    res.send('Not ready yet');
+});
+
+//Finally start the app with the given port number
+app.listen(4000, () => console.log('Example app listening on port 4000!'));
+
+

Let's check if it works, run the service with node.

+
node index.js
+Example app listening on port 4000!
+
+

Open the browser and check if it prints our hello message when accessing localhost:4000. Works? Greate. Now let's work with the image and see how we do it. To optimize our image, we'll use the library imagemin and imagemin-pngquant, it will be that simple for now, we'll work with rabbitmq latter.

+
const imagemin = require('imagemin');
+const imageminPngquant = require('imagemin-pngquant');
+//...
+
+//The path that will handle the image file and throw them to the queue
+app.post('/upload', (req, res) => {
+    let img = req.files.image; //"image" is the name of the input
+
+            imagemin.buffer(img.data, {
+        plugins: [imageminPngquant()]
+    })
+    .then(out => {
+        res.write(out,'binary');
+        res.end(null, 'binary');
+    });
+});
+
+    //...
+
+

Use Postman to test the request. To see if it will work, make a request to http://localhost:4000/upload with a formdata with a file. Select the "send and Download" instead of "Send" and you should have an image after that. Bellow an image of how your postman should be.

+Postman +

That's it for today, next week we'll change our code to use RabbitMQ.

+

+
+ + +
+
+

Translations:

+
    +
+
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/microservices_nodejs_express_rabbitmq_part_1.html.gz b/microservices_nodejs_express_rabbitmq_part_1.html.gz new file mode 100644 index 000000000..104d0b601 Binary files /dev/null and b/microservices_nodejs_express_rabbitmq_part_1.html.gz differ diff --git a/microservices_nodejs_express_rabbitmq_part_2.html b/microservices_nodejs_express_rabbitmq_part_2.html new file mode 100644 index 000000000..5549fa8e9 --- /dev/null +++ b/microservices_nodejs_express_rabbitmq_part_2.html @@ -0,0 +1,579 @@ + + + + + + + + Microservices with NodeJS, Express.js and RabbitMQ Part 2 - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+ + +
+

If you haven't read the part 1 go ahead and read it... It can be useful :). Or if for some reason you want to start now, you can grab the project where we stopped here and get along. On this part, we'll implement the RabbitMQ queue and see how we can get the best of our app and server with that.

+

Before we began coding, let's understand why we are going to use RabbitMQ if what we have now works? If you check again, you'll see how long it takes to answer the request with the optimized image. It takes a few seconds, so imagine an online service with thousands of request to optimize images (like TinyPNG) how long is it gonna take to answer every request? How much of your server is it gonna take? With only one service running, probably the server will crash.

+

With a queue, we can schedule the requests so we can use the amount of memory and processor that our server has, without taking more than we can. It's better to take a few seconds to answer the request then throw some error to the user. Want more? With RabbitMQ we can see how the queue is doing and we can add more consumers (workers) to it and get things done quicker and distribute the job.

+

First of all, we need an up and running Rabbit server, for the sake of simplicity, I'll use a Docker container with it inside.

+
docker run -d --name rabbit -p 5672:5672 -p 8080:15672 rabbitmq:3-management
+
+

You can see that we're running the rabbitmq:3-management image, which provides us a web interface to see how things are going. After that, if you look at our code you'll see that all the job is made at the '/upload' route, and that's what we'll change.

+

First, we need to understand what we need from RabbitMQ. We need something that, we send an image to a queue and get an optimized image back from that. There is a name for that, is RPC (remote procedure call) and there are two ways of doing this with rabbit. Both the ways you can see on their tutorial page. We'll use the approach that uses a global channel whose id is randomly generated (you'll use the name 'amq.rabbitmq.reply-to' but the rabbit will do the job).

+

Let's start importing the library, defining a few variables and defining a init function that will establish a connection with the rabbit server and create our RPC queue. The RPC queue it's where we'll receive the answer from the consumer (our worker).

+
//import the library
+const amqplib = require('amqplib');
+
+//queue channel
+let channel = null;
+//queue name
+const QUEUE = 'optimizeimg';
+
+//...
+
+function init() {
+    return require('amqplib').connect('amqp://localhost')
+        .then(conn => conn.createChannel())
+        .then(ch => {
+            channel = ch;
+
+            //this queue is a "Direct reply-to" read more at the docs
+            //When some msg comes in, we "emit" a message to the proper "correlationId" listener
+            ch.consume('amq.rabbitmq.reply-to', msg => eventEmitter.emit(msg.properties.correlationId, msg.content), {noAck: true});
+        });
+}
+
+//Random id generator
+function randomid() {
+    return new Date().getTime().toString() + Math.random().toString() + Math.random().toString();
+}
+
+app.post('/upload', (req, res) => {
+    let img = req.files.image;
+
+    let id = randomid();
+
+    //Event listener that will fire when the proper randomid is provided
+    eventEmitter.once(id, msg => {
+        res.write(msg, 'binary');
+        res.end(null, 'binary');
+    });
+
+    //Checks if the queue exists, and create it if needed.
+    channel.assertQueue(QUEUE)
+        //Sent the buffered img to the queue with the ID and the responseQueue
+        .then(() => channel.sendToQueue(QUEUE, img.data, {correlationId:id, replyTo: 'amq.rabbitmq.reply-to'}));
+
+});
+
+//Finally start the app with the given port number
+//now we initialize the rabbitmq connection before start the server
+init()
+    .then(() => app.listen(4000, () => console.log('Example app listening on port 4000!')))
+    .catch(err=>console.error(err));
+
+

Ok, now we have our server code rewritten so let's see our worker code. Create a file named 'worker.js' and let's see how it's gonna be. It's really simple. You initialize a connection with RabbitMQ too, create a channel, check if the queue exists and start watching for incoming messages. When an image arrives, we do the job with it and send back to the "replyTo" queue the optimized image for the proper sender (correlationId). In the end, we do an acknowledge of the message so it get's out from the queue.

+
const imagemin = require('imagemin');
+const imageminPngquant = require('imagemin-pngquant');
+
+let channel = null;
+const QUEUE = 'imgqueue';
+
+require('amqplib').connect('amqp://localhost')
+.then(conn =>conn.createChannel())
+.then(ch => {
+    ch.assertQueue(QUEUE)
+    .then(() => {
+        //Watch incomming messages
+        ch.consume(QUEUE, msg => {
+            imagemin.buffer(msg.content, {
+                plugins: [imageminPngquant()]
+            })
+            .then(out => {
+                //Send back to the sender (replyTo) queue and give the correlationId back
+                //so we can emit the event.
+                ch.sendToQueue(msg.properties.replyTo, out, {
+                    correlationId: msg.properties.correlationId
+                });
+
+                //Acknowledge the job done with the message.
+                ch.ack(msg);
+            });
+        });
+    });
+});
+
+

The key points here are. Open just one connection to the hole server. You CAN create one channel for every request that you receive, but it can take some time if you have a really big cluster of RabbitMQ. It was a quick tutorial, but I hope that it was able to clear a few questions that you might have when working with rabbit and express.

+

+
+ + +
+
+

Translations:

+
    +
+
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/microservices_nodejs_express_rabbitmq_part_2.html.gz b/microservices_nodejs_express_rabbitmq_part_2.html.gz new file mode 100644 index 000000000..3c82ad9f0 Binary files /dev/null and b/microservices_nodejs_express_rabbitmq_part_2.html.gz differ diff --git a/microsoft-against-covid.html b/microsoft-against-covid.html new file mode 100644 index 000000000..6839de1b5 --- /dev/null +++ b/microsoft-against-covid.html @@ -0,0 +1,510 @@ + + + + + + + + Microsoft Against Covid - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Microsoft Against Covid

+
+ +
+
+ +
+

Has your job been affected by covid? Well, last week I've posted on Grepora about a Free Certification Voucher that Microsoft was giving away at the Microsoft Ignite event. After that, I found that they were also giving a huge discount to people who have had their job affected by covid pandemic.

+

To see more details about if you were eligible, access https://docs.microsoft.com/en-us/learn/certifications/skillingoffer.

+
+ + +
+
+

Translations:

+ +
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/microsoft-against-covid.html.gz b/microsoft-against-covid.html.gz new file mode 100644 index 000000000..881176bca Binary files /dev/null and b/microsoft-against-covid.html.gz differ diff --git a/monitoring-mysql-replication-with-powershell.html b/monitoring-mysql-replication-with-powershell.html new file mode 100644 index 000000000..3fd365af1 --- /dev/null +++ b/monitoring-mysql-replication-with-powershell.html @@ -0,0 +1,575 @@ + + + + + + + + Monitoring MySQL Replication Status with PowerShell - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+ + +
+

I've been migration some bash scripts that I have to PowerShell, and it's time to migrate a script that monitors the replication of a MySQL database. The credit for the original script goes to Paweł. It's a simple script where I seek a few tags/fields that we get from SHOW SLAVE STATUS\G command, the fields are. Slave_IO_Running, Slave_SQL_Running, and Seconds_Behind_Master. I still need to figure out the proper way to store/read variables like usernames and passwords, if you have any tips, feel free to even make a pull request (here) at the git where I'll store some scripts.

+
<#
+   Variables definition
+#>
+$MaxSeconds = 120  # Max seconds behind master allowed
+$MysqlUser  = 'root'
+$MysqlPass  = ''
+
+$MailTo     = 'mauricio@sipmann.com'
+$MailFrom   = 'mauricio@sipmann.com'
+
+
+$data = $(mysql -u $MysqlUser -p"$MysqlPass" -e 'SHOW SLAVE STATUS \G')
+
+#Debug data
+#$data = Get-Content 'c:\temp\sampleresult.txt'
+
+<# Parse the data #>
+$IORunning   = (($data | Where-Object { $_ -match 'Slave_IO_Running:' }) -split '\s+')[2]
+$SQLRunning  = (($data | Where-Object { $_ -match 'Slave_SQL_Running:' }) -split '\s+')[2]
+$LastErrNo   = (($data | Where-Object { $_ -match 'Last_Errno' }) -split '\s+')[2]
+$SecondsBh   = [int](($data | Where-Object { $_ -match 'Seconds_Behind_Master' }) -split '\s+')[2]
+
+If ($IORunning -Eq 'No' -Or $SQLRunning -Eq 'No' -Or $SecondsBh -gt $MaxSeconds) {
+    $MailBody = '<h1>Problema na replicação</h1><br>'
+
+    $MailBody += '    IO Running: ' + ($IORunning)  + '<br>'
+    $MailBody += '   SQL Running: ' + ($SQLRunning) + '<br>'
+    $MailBody += 'Seconds Behind: ' + ($SecondsBh) + '<br>'
+    $MailBody += '   Last Err No: ' + ($LastErrNo) + '<br>'
+
+    <# Send e-mail, maybe some telegram message here too #>
+    Send-MailMessage -To $MailTo -From $MailFrom  -Subject 'Problemas na replicação' -bodyAsHtml $MailBody -Credential (Get-Credential) -SmtpServer 'smtp.office365.com' -Port 587 -UseSsl
+} Else {
+    Write-Host "Up and running"
+}
+

+
+ + +
+
+

Translations:

+ +
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/monitoring-mysql-replication-with-powershell.html.gz b/monitoring-mysql-replication-with-powershell.html.gz new file mode 100644 index 000000000..1ba05752b Binary files /dev/null and b/monitoring-mysql-replication-with-powershell.html.gz differ diff --git a/monitoring-mysql-restarts-with-powershell.html b/monitoring-mysql-restarts-with-powershell.html new file mode 100644 index 000000000..a3700b5b2 --- /dev/null +++ b/monitoring-mysql-restarts-with-powershell.html @@ -0,0 +1,539 @@ + + + + + + + + Monitoring MySQL restarts with PowerShell - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Monitoring MySQL restarts with PowerShell

+
+ +
+
+ +
+

Hey folks, it's time for another PowerShell script. If you haven't seen the other ones, check the links below.

+ +

Well, this one it's a pretty simple script, but again, if your customer doesn't have a Zabbix server or doesn't allow you to setup one to do the monitoring, a set of scripts can be handy. We start executing some basic query SHOW GLOBAL STATUS LIKE 'Uptime', with that we'll get exactly what we're looking for.

+

If for some reason, the command fails (watch for the "global" variable called $lastExitCode), we send an e-mail telling you about that connection problem.

+

And then, we get to the part where we parse the value, this one is pretty similar to the parse we did on the first post about using PowerShell to monitor MySQL. But we basically look for the Value line, split it by space and then parse the second position to an integer. And then all we have to do is check if the uptime is lower than our threshold, if it is we send an e-mail.

+
$MailFrom = 'maurio[at]sipmann.com'
+$MailTo   = 'mauricio[at]sipmann.com'
+$MysqlHost = '127.0.0.1'
+$MysqlUser = 'root'
+$MysqlPass = '123'
+
+
+$data = $(mysql -h $MysqlHost -u $MysqlUser -p"$MysqlPass" -e "SHOW GLOBAL STATUS LIKE 'Uptime' \G")
+
+<# Unable to execute the sql Command #>
+if ($lastExitCode -eq 1) {
+    Send-MailMessage -To $MailTo -From $MailFrom  -Subject 'Connection problem' -bodyAsHtml "Connection problem on host ${MysqlHost}" -Credential Get-Credential -SmtpServer 'smtp.office365.com' -Port 587 -UseSsl
+    exit
+}
+
+$UpTime   = [int](($data | Where-Object { $_ -match 'Value:' }) -split '\s+')[2]
+
+<# If the uptime is lower then 20 minutes #>
+if ($UpTime -lt 1200) {
+    Send-MailMessage -To $MailTo -From $MailFrom -Subject "MySQL Restarted" -bodyAsHtml "MySQL host ${MysqlHost} restarted less than 20 minutes ago" -Credential Get-Credential -SmtpServer 'smtp.office365.com' -Port 587 -UseSsl
+}
+
+ +

This script (and the other ones I use) is available at my GitHub here. Keep in mind that the ones on the GitHub repo, are a little different from here.

+
+ + +
+
+

Translations:

+ +
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/monitoring-mysql-restarts-with-powershell.html.gz b/monitoring-mysql-restarts-with-powershell.html.gz new file mode 100644 index 000000000..6122c067e Binary files /dev/null and b/monitoring-mysql-restarts-with-powershell.html.gz differ diff --git a/monitoring-website-heath-with-azure-functions.html b/monitoring-website-heath-with-azure-functions.html new file mode 100644 index 000000000..90528ec73 --- /dev/null +++ b/monitoring-website-heath-with-azure-functions.html @@ -0,0 +1,618 @@ + + + + + + + + Monitoring a Website heath with Azure Functions - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+ + +
+

Sometimes you get your self in need to monitor a website's health or it's content for changes. Of course, there's plenty of options out there, but for the sake of curiosity, let's code our own to see what we can do. First things first. Everything you'll see here, you can achieve with the free tier of azure.

+

The main idea of our app will be to monitor website health (status code). To create a new Azure Function Project, follow the steps below.

+

Steps to create a azure function project

+

After creating the project, you'll have a few files. Open your main file and start coding. The main file will have a function called Run and you can code your request method. I've created an async method to make the request and log the output at the console. The full code you can see below.

+
using System;
+using System.Linq;
+using System.Net.Http;
+using System.Threading.Tasks;
+using Microsoft.Azure.WebJobs;
+using Microsoft.Azure.WebJobs.Host;
+using Microsoft.Extensions.Logging;
+
+namespace Sipmann.CheckMySite
+{
+    public static class HttpCheck
+    {
+
+        private static async Task GetTask(string url, ILogger log)
+        {
+            var request = new HttpRequestMessage(HttpMethod.Get, url);
+
+            var client = new HttpClient();
+            var response = await client.SendAsync(request);
+
+            if (response.IsSuccessStatusCode)
+            {
+                log.LogInformation($"URL ${url} esta OK");
+            }
+            else
+            {
+                log.LogInformation($"URL ${url} não esta OK");
+            }
+        }
+
+        [FunctionName("HttpCheck")]
+        public static void Run([TimerTrigger("0 */5 * * * *")]TimerInfo myTimer, ILogger log)
+        {
+            var urls = new[]{"https://www.sipmann.com", "https://www.canezecanez.com.br"};
+
+            // Start every request and wait for them all to complete
+            Task.WaitAll(urls.Select(url => GetTask(url, log)).ToArray());
+            log.LogInformation($"Finalizou a fila");
+        }
+    }
+}
+
+ +

Now you can enhance the function and maybe send some alerts like a Telegram message when one of your sites went down.

+
+ + +
+
+

Translations:

+ +
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/monitoring-website-heath-with-azure-functions.html.gz b/monitoring-website-heath-with-azure-functions.html.gz new file mode 100644 index 000000000..60c2d9907 Binary files /dev/null and b/monitoring-website-heath-with-azure-functions.html.gz differ diff --git a/mysql-dual-password-functionality.html b/mysql-dual-password-functionality.html new file mode 100644 index 000000000..fa5ba63bb --- /dev/null +++ b/mysql-dual-password-functionality.html @@ -0,0 +1,519 @@ + + + + + + + + Changing a MySQL user password across multiple application instances without downtime - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+ + +
+

Do you need to change the password of a MySQL user that it's being used in an application, and can't allow a single downtime? Well, MySQL 8.0.14 came with a feature called Dual Password Support, with it you can change the password keeping the previous password as a kind of backup. That way you still can log in using the old password or can start using the new one. With that, the password change workflow it's the following.

+

1) Change password keeping the old one;

+

2) Deploy the new config to your app/cluster;

+

3) Discard the old password.

+

To change the password and keep the old one, you have the following command.

+
ALTER USER 'appuser'@'localhost' IDENTIFIED BY 'new_password' RETAIN CURRENT PASSWORD;
+
+ +

To discard the old one, run the following.

+
ALTER USER 'appuser'@'localhost' DISCARD OLD PASSWORD;
+
+ +

And you are done. Hope you find it as useful as I :)

+
+ + +
+
+

Translations:

+ +
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/mysql-dual-password-functionality.html.gz b/mysql-dual-password-functionality.html.gz new file mode 100644 index 000000000..7e97c3f8d Binary files /dev/null and b/mysql-dual-password-functionality.html.gz differ diff --git a/now_posting_on_grepora.html b/now_posting_on_grepora.html new file mode 100644 index 000000000..e764b2dd8 --- /dev/null +++ b/now_posting_on_grepora.html @@ -0,0 +1,406 @@ + + + + + + + + Now posting on Grepora - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Now posting on Grepora

+
+ +
+
+ +
+

A few weeks ago I started posting at Grepora blog. If you like or are looking for some Oracle related stuff, Grepora it's a good place to go and spend a time reading :). From time to time I'll be posting there, it doesn't mean that this blog will be closed or anything like that, but probably this one will be more focused on Front-end stuff, a few tricks with linux and a lil less with Java.

+

+
+ + +
+
+

Translations:

+
    +
+
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/now_posting_on_grepora.html.gz b/now_posting_on_grepora.html.gz new file mode 100644 index 000000000..cb0ff2bb5 Binary files /dev/null and b/now_posting_on_grepora.html.gz differ diff --git a/pages/about.html b/pages/about.html new file mode 100644 index 000000000..44fc57f5a --- /dev/null +++ b/pages/about.html @@ -0,0 +1,304 @@ + + + + + + + + About - Sipmann + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+

About

+ +
+ +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pages/about.html.gz b/pages/about.html.gz new file mode 100644 index 000000000..093491dd7 Binary files /dev/null and b/pages/about.html.gz differ diff --git a/pages/cartao-pt.html b/pages/cartao-pt.html new file mode 100644 index 000000000..bad8233de --- /dev/null +++ b/pages/cartao-pt.html @@ -0,0 +1,480 @@ + + + + + + + + cartao - Sipmann + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+

cartao

+ +
+ + +
+
+ +
+
+
+
+

Consultoria Cloud

+

+ Projetos de implantação e acompanhamento de sua cloud. Otimize seus custos de infraestrutura levando o seu DR para a nuvem da forma mais transparente. +

+

Mais Detalhes

+
+
+
+
+
+
+ +
+
+
+
+

Gestão De Banco

+

+ Gerenciamento, manutenção e acompanhamento do seu banco de dados SQL Server. Com foco na segurança e velocidade de resposta em consultas. +

+

Mais Detalhes

+
+
+
+
+
+
+ +
+
+
+
+

Power BI

+

+ Dashboards analíticos para análise e tomadas de decisões do seu negócio. Baixe um dashboard e analise o faturamento do seu ERP Protheus. +

+

Mais Detalhes

+
+
+
+
+
+
+ +
+
+
+
+

Monitoramento

+

+ Monitoramento de sua infraestrutura, aplicações e bancos de dados. Fornecendo relatórios detalhados desde avisos, erros até o uptime de serviços críticos. +

+

Mais Detalhes

+
+
+
+
+
+
+ +
+
+

Consultoria cloud

+
+
+

+
+
+ +
+
+

Meus Serviços

+
+
+

Has your job been affected by covid? Well, last week I've posted on Grepora about a Free Certification Voucher that Microsoft was giving away at the Microsoft Ignite event. After that, I found that they were also giving a huge discount to people who have had their job affected by …

+
+ + +
+

+ View comments +

+
+
+
+
+ + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pages/cartao-pt.html.gz b/pages/cartao-pt.html.gz new file mode 100644 index 000000000..e5bec234b Binary files /dev/null and b/pages/cartao-pt.html.gz differ diff --git a/pt/apache-nifi-json-to-sql-replacing-underscore.html b/pt/apache-nifi-json-to-sql-replacing-underscore.html new file mode 100644 index 000000000..877ec0883 --- /dev/null +++ b/pt/apache-nifi-json-to-sql-replacing-underscore.html @@ -0,0 +1,411 @@ + + + + + + + + Apache Nifi JSON to SQL removendo underline - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Apache Nifi JSON to SQL removendo underline

+
+ +
+
+ +
+

Recentemente eu estava desenvolvendo alguns processos de ETL com o Apache NiFi. Mas após alguns minutos desenhando o meu fluxo, eu vi um comportamento estranho do componente ConvertJSONToSQL, que estava substituindo os underline ('_') do nome de um campo utilizado na condição da SQL (eu estava preparando um UPDATE). Aquilo estava estranho, uma vez que na definição do SET da SQL, o nome do campo permanecia inalterado. Depois de algumas pesquisas, achei uma doc que a propriedade (veja abaixo) Translate Field Names era a responsável por este comportamento estranho.

+

Apache NiFi JSONToSQL config

+

Antes de definir a propriedade como FALSE, esteja ciente que as propriedades do seu JSON devem ser exatamente iguais aos nomes dos campos da sua tabela.

+
+ + +
+
+

Traduções:

+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/apache-nifi-json-to-sql-replacing-underscore.html.gz b/pt/apache-nifi-json-to-sql-replacing-underscore.html.gz new file mode 100644 index 000000000..829b4bc2f Binary files /dev/null and b/pt/apache-nifi-json-to-sql-replacing-underscore.html.gz differ diff --git a/pt/archives.html b/pt/archives.html new file mode 100644 index 000000000..4c5a61f41 --- /dev/null +++ b/pt/archives.html @@ -0,0 +1,344 @@ + + + + + + + + Sipmann - Archives + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/archives.html.gz b/pt/archives.html.gz new file mode 100644 index 000000000..1014c94a3 Binary files /dev/null and b/pt/archives.html.gz differ diff --git a/pt/author/mauricio-camargo-sipmann.html b/pt/author/mauricio-camargo-sipmann.html new file mode 100644 index 000000000..6718d00b6 --- /dev/null +++ b/pt/author/mauricio-camargo-sipmann.html @@ -0,0 +1,603 @@ + + + + + + + + Sipmann - Articles by Maurício Camargo Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+ +
+
+
+

Apache Nifi JSON to SQL removendo underline

+
+ +
+
+ +
+

Recentemente eu estava desenvolvendo alguns processos de ETL com o Apache NiFi. Mas após alguns minutos desenhando o meu fluxo, eu vi um comportamento estranho do componente ConvertJSONToSQL, que estava substituindo os underline ('_') do nome de um campo utilizado na condição da SQL (eu estava preparando um UPDATE). Aquilo …

+
+ + + +
+
+
+
+ +
+
+ + + + + + + +
+

Então, você utiliza Entity Framework Core e geralmente faz o seu selecto da seguinte forma, talvez você está retornando muitos dados.

+
var products = Products
+    .Where(p => p.UnitsInStock > 0)
+    .OrderBy(p => p.ProductName)
+    .ToList()
+
+ +

Rodando a query acima, em uma base de testes você obtem o seguinte resultado, veja quantas …

+
+ + + +
+
+
+
+
+ + + + + +
+

Zabbix Running on Low Memory Mode

+
+ +
+
+ +
+

Olá pessoal! Trago hoje outro post sobre Zabbix. Este é sobre aumentar o cache do seu Zabbix Server. É perfeitamente comum (se você roda com as configurações padrões) receber avisos sobre Zabbix value cache running on low memory mode no seu dashboard ou arquivos de log.

+

Zabbix Dashboard alertando sobre problemas de memória +Zabbix Dashboard cache gráfico com 70% utilizado

+

Para resolver, abra o …

+
+ + + +
+
+
+
+
+ + + + + + + +
+

Tenho migrado alguns scripts bash que tenho para PowerShell, e chegou a vez de migrar um script de monitoramento de replicação do MySQL. Fica como crédito o script original do Paweł. É um script bem simples onde eu verifico algumas tags resultantes do SHOW SLAVE STATUS\G, são elas. Slave_IO_Running …

+
+ + + +
+
+
+
+
+
+

Microsoft Contra Covid

+
+ +
+
+ +
+

Você teve seu trabalho afetado pela pandemia do covid? Bom, na última semana eu postei no Grepora sobre um Voucher para certificação gratuita que a Microsoft estava distribuindo durante o evento Microsoft Ignite. Depois disto, eu fiquei sabendo que eles também estão entregando grandes discontos para quem teve o seu …

+
+ + + +
+
+
+
+
+ + + + + +
+

O poder do PowerShell

+
+ +
+
+ +
+

Como um usuário linux por muito tempo, eu automatizei algumas tarefas com scripts bash e fiquei longe do PowerShell... Voltei a utilizar Windows alguns anos atrás e ainda assim, não dei uma chance ao PS. Mas porque não? Eu fiz alguns scripts para automatizar algumas tarefas em um servidor Protheus …

+
+ + + +
+
+
+
+
+ + + + + +
+

Top Level Statement no C# 9

+
+ +
+
+ +
+

Olá pessoal, venho hoje falar sobre uma novidade que estará disponível na versão 9 do C#. Toda vez que você deseja criar um novo projeto, você sempre tem o mesmo arquivo Main, com a mesma estrutura. Na próxima versão do C# (versão 9), nós teremos uma nova funcionalidade chamada Top …

+
+ + + +
+
+
+
+
+ + 1 + 2 + 3 + » + +
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/author/mauricio-camargo-sipmann.html.gz b/pt/author/mauricio-camargo-sipmann.html.gz new file mode 100644 index 000000000..df1d0c10a Binary files /dev/null and b/pt/author/mauricio-camargo-sipmann.html.gz differ diff --git a/pt/author/mauricio-camargo-sipmann2.html b/pt/author/mauricio-camargo-sipmann2.html new file mode 100644 index 000000000..c9dd6bda5 --- /dev/null +++ b/pt/author/mauricio-camargo-sipmann2.html @@ -0,0 +1,574 @@ + + + + + + + + Sipmann - Articles by Maurício Camargo Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Zabbix poller processes more than 75%

+
+ +
+
+ +
+

Este é o terceiro post sobre configurações para o Zabbix. Todas as alterações que eu sugiro nestes posts, são baseadas em um servidor com 50+ hosts. Outro problema que pode ocorrer em seu servidor, é o poller de informações ficar sobrecarregado pela quantidade de servidores que ele precisa pegar carga …

+
+ + + +
+
+
+
+
+ + + + + + + +
+

Algumas vezes você se depara com a necessidade de monitorar a disponibilidade de um website ou mudanças em seu conteúdo. É claro que temos diversas opções disponíveis no mercado, mas para fins de curiosidade, vamos programar o nosso próprio e ver o que podemos fazer. Primeiramente, tudo que você ver …

+
+ + + +
+
+
+
+
+
+

Zabbix ICMP pinger processes more than 75%

+
+ +
+
+ +
+

Então o seu systema de monitoramento creasceu e o seu Zabbix começou a printar "Zabbix icmp pinger processes more than 75% busy" no seu dashboard.

+

Dashboard do zabbix avisando sobre o erro

+

Tudo que você tem a fazer é abrir o seu arquivo de configuração (/etc/zabbix/zabbix_server.conf) e localizar a tag chamada StartPingers. Ela deve …

+
+ + + +
+
+
+
+
+
+

Zabbix Server Out of Memory

+
+ +
+
+ +
+

Você tem um servidor Zabbix crashando e observando o arquivo de log /var/log/zabbix/zabbix_server.log você localiza a seguinte mensagem referênciando falta de memória?

+
__mem_malloc: skipped 0 asked 24 skip_min 18446744073709551615 skip_max 0
+[file:dbconfig.c,line:94] __zbx_mem_realloc(): out of memory (requested 16 bytes)
+[file:dbconfig.c …

+
+ + + +
+
+
+
+
+
+

Removendo um usuário de uma base SQL Server

+
+ +
+
+ +
+

O seu cliente lhe pede com urgência para dropar um usuário da sua base MsSQL Server, mas você trava com o seguinte aviso de erro:

+
Error: 15138 The database principal owns a schema in the database, and cannot be dropped.
+
+ +

Se você não possui (ou no momento não consegue acesso …

+
+ + + +
+
+
+
+ +
+
+
+

Menu dinâmico com as apps do django

+
+ +
+
+ +
+

Digamos que sua empresa trabalha com Django desenvolvendo aplicações cujas apps são plugaveis e reutilizáveis. Por que não se aproveitar de um certo padrão de desenvolvimento para desenvolver menus que se modificam de acordo com as apps que estão no projeto? Como o objetivo aqui não é desenvolver uma app …

+
+ + + +
+
+
+
+
+
+

Scripts de inicialização no raspberry pi

+
+ +
+
+ +
+

Instalei essa semana o gitea no meu raspberry pi B + e queria iniciar ele no boot... Não sou profundo conhecedor de linux, então, logo não sabia como fazer isto da melhor forma. +As versões atuais do Raspbian utilizam o systemd para gerenciar os serviços e confesso que nunca havia utilizado …

+
+ + + +
+
+
+
+
+
+

Cool Tools

+
+ +
+
+ +
+

Com o passar do tempo você vai "encontrando" - e às vezes até mesmo desenvolvendo - algumas ferramentas que tornam o seu dia a dia como desenvolvedor mais fácil. Abaixo seguem algumas das minhas ferramentas que costumo usar. Ressalto que essa lista será (provavelmente) atualizada com o passar do tempo.

+

+
+ + + +
+
+
+
+
+
+

Desenvolvendo apps para o FirefoxOS (Parte 1)

+
+ +
+
+ +
+

Requisitos mínimos?

+

Para seguir este tutorial você precisará do Nodejs. Utilizaremos ele para automatizar algumas tarefas, como a criação do nosso projeto e até mesmo o empacotamento da app. Estas automatizações se darão pela utilização de algumas aplicações como o Yeoman e o Grunt .

+

Também será necessário o emulador do …

+
+ + + +
+
+
+
+
+ « + + 1 + 2 + 3 + » + +
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/author/mauricio-camargo-sipmann2.html.gz b/pt/author/mauricio-camargo-sipmann2.html.gz new file mode 100644 index 000000000..a9e00f7b0 Binary files /dev/null and b/pt/author/mauricio-camargo-sipmann2.html.gz differ diff --git a/pt/author/mauricio-camargo-sipmann3.html b/pt/author/mauricio-camargo-sipmann3.html new file mode 100644 index 000000000..70db003ab --- /dev/null +++ b/pt/author/mauricio-camargo-sipmann3.html @@ -0,0 +1,333 @@ + + + + + + + + Sipmann - Articles by Maurício Camargo Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Editando o Admin do Django

+
+ +
+
+ +
+

Este artigo foi re-postado no grupo PythonClub. Vamos falar um pouco sobre como customizar o admin do Django. Primeiramente porque? A resposta é bem simples, quero mostrar algo para o usuário sem que ele precise entrar nas apps e fazer alguma consulta para então tomar alguma ação. Alguns exêmplos para …

+
+ + + +
+
+
+
+
+ « + + 1 + 2 + 3 + +
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/author/mauricio-camargo-sipmann3.html.gz b/pt/author/mauricio-camargo-sipmann3.html.gz new file mode 100644 index 000000000..62bac83ca Binary files /dev/null and b/pt/author/mauricio-camargo-sipmann3.html.gz differ diff --git a/pt/authors.html b/pt/authors.html new file mode 100644 index 000000000..4db2a09c3 --- /dev/null +++ b/pt/authors.html @@ -0,0 +1,302 @@ + + + + + + + + Sipmann - Authors + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+

Authors on Sipmann

+ +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/authors.html.gz b/pt/authors.html.gz new file mode 100644 index 000000000..516225fe0 Binary files /dev/null and b/pt/authors.html.gz differ diff --git a/pt/blocking-user-on-sql-server-based-on-schedule.html b/pt/blocking-user-on-sql-server-based-on-schedule.html new file mode 100644 index 000000000..463220825 --- /dev/null +++ b/pt/blocking-user-on-sql-server-based-on-schedule.html @@ -0,0 +1,538 @@ + + + + + + + + Bloqueando um usuário do SQL Server baseado em uma tabela de horários - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+ + +
+

Ok, algum tempo atrás, eu postei sobre como você pode impor limites às conexões do SQL Server utilizando o Resource Governor. Mas, e se você não pode utilizar ele? Você sempre pode bloquear logins usando uma trigger, mas eu não gosto da ideia de ter um select rodando a cada login. Então, eu cheguei a esta solução, utilizando uma stored procedure, uma tabela e o Agent.

+

A ideia principal é armazenar o horário em que um usuário deve ser bloqueado pelo Agent. Abaixo você pode ver a criação da tabela:

+
CREATE TABLE dbo.HorariosBloqueio (
+    Id INT NOT NULL,
+    LoginName NVARCHAR(100) NOT NULL,
+    HrInicio TIME NOT NULL, /* horário de inicio do bloqueio */
+    HrTermino TIME NOT NULL, /*horário de termino */
+    Bloqueado INT DEFAULT 0, /* 0 = desbloqueado, 1 = bloqueado */
+    PRIMARY KEY (Id)
+);
+GO
+
+/* regra para Não bloquear o usuário SA */
+ALTER TABLE dbo.HorariosBloqueio
+    ADD CONSTRAINT chk_users CHECK (LoginName not in ('sa'));
+
+ALTER TABLE dbo.HorariosBloqueio
+    ADD CONSTRAINT chk_hora_final_maior CHECK (HrTermino > HrInicio);
+
+ALTER TABLE dbo.HorariosBloqueio
+    ADD CONSTRAINT chk_status_bloqueio CHECK (Bloqueado in (0, 1));
+
+CREATE SEQUENCE dbo.seq_HorariosBloqueio START WITH 1 INCREMENT BY 1;
+GO
+
+ +

Depois de criar a tabela, vamos verificar a procedure que vai fazer todo o trabalho de habilitar/desabilitar os usuários. Fique ciente que, nesta procedure, eu defini o nome do banco onde a tabela está armazenada. Você pode substituir o nome DBATOOLS pelo o nome da sua base.

+
IF OBJECT_ID('dbo.sp_ValidarLogin') IS NULL
+  EXEC ('CREATE PROCEDURE dbo.sp_ValidarLogin AS RETURN 0;');
+GO
+
+CREATE OR ALTER PROC dbo.sp_ValidarLogin
+AS BEGIN
+    DECLARE @LoginName AS NVARCHAR(100);
+    DECLARE @Momento AS TIME;
+    SET @Momento = CAST(GETDATE() AS TIME);
+
+    /* Bloqueia os que ainda não estiverem bloqueados de acordo com a hora atual */
+    DECLARE block_cursor CURSOR
+        FOR SELECT LoginName FROM [DBATOOLS].[dbo].[HorariosBloqueio] WHERE Bloqueado = 0 AND HrInicio <= @Momento AND HrTermino >= @Momento
+    OPEN block_cursor;
+
+    FETCH NEXT FROM block_cursor INTO @LoginName
+
+    WHILE @@FETCH_STATUS = 0
+    BEGIN
+        exec ('ALTER LOGIN ' + @LoginName + ' DISABLE;');
+
+        print 'Bloqued usuario ' + @LoginName;
+
+        FETCH NEXT FROM block_cursor INTO @LoginName
+    END;
+
+    CLOSE block_cursor;
+    DEALLOCATE block_cursor;
+
+    UPDATE [DBATOOLS].[dbo].[HorariosBloqueio] SET Bloqueado = 1 WHERE HrInicio <= @Momento AND HrTermino >= @Momento
+
+
+    /* Libera quem estava bloqueado */
+    DECLARE unblock_cursor CURSOR
+        FOR SELECT LoginName FROM [DBATOOLS].[dbo].[HorariosBloqueio] WHERE Bloqueado = 1 AND (HrInicio > @Momento OR HrTermino < @Momento)
+    OPEN unblock_cursor ;
+
+    FETCH NEXT FROM unblock_cursor  INTO @LoginName
+
+    WHILE @@FETCH_STATUS = 0
+    BEGIN
+        exec ('ALTER LOGIN ' + @LoginName +' ENABLE;');
+
+        print 'Unbloqued usuario ' + @LoginName;
+
+        FETCH NEXT FROM unblock_cursor  INTO @LoginName
+    END;
+
+    CLOSE unblock_cursor;
+    DEALLOCATE unblock_cursor;
+
+    UPDATE [DBATOOLS].[dbo].[HorariosBloqueio] SET Bloqueado = 0 WHERE Bloqueado = 1 AND (HrInicio > @Momento OR HrTermino < @Momento)
+END;
+
+ +

Certo, então agora tudo que temos que fazer é definir o job no Agent para rodar a procedure de minuto em minuto. Novamente, a ideia principal é chamar a procedure quando um usuário deve ser bloqueado e quando deve ser desbloqueado.

+
    -- Vai bloquear o usuário protheus das 10 AM até 15 PM
+    INSERT INTO dbo.HorariosBloqueio (Id, LoginName, HrInicio, HrTermino) VALUES (NEXT VALUE FOR seq_HorariosBloqueio, 'protheus', '10:00:00', '15:00:00');
+

+
+ + +
+
+

Traduções:

+ +
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/blocking-user-on-sql-server-based-on-schedule.html.gz b/pt/blocking-user-on-sql-server-based-on-schedule.html.gz new file mode 100644 index 000000000..3b601f3dc Binary files /dev/null and b/pt/blocking-user-on-sql-server-based-on-schedule.html.gz differ diff --git a/pt/categories.html b/pt/categories.html new file mode 100644 index 000000000..aebab3f69 --- /dev/null +++ b/pt/categories.html @@ -0,0 +1,312 @@ + + + + + + + + Sipmann - Categories + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+

Categories on Sipmann

+ +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/categories.html.gz b/pt/categories.html.gz new file mode 100644 index 000000000..64625f695 Binary files /dev/null and b/pt/categories.html.gz differ diff --git a/pt/category/azure.html b/pt/category/azure.html new file mode 100644 index 000000000..21f8aa51e --- /dev/null +++ b/pt/category/azure.html @@ -0,0 +1,336 @@ + + + + + + + + Sipmann - Azure category + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Microsoft Contra Covid

+
+ +
+
+ +
+

Você teve seu trabalho afetado pela pandemia do covid? Bom, na última semana eu postei no Grepora sobre um Voucher para certificação gratuita que a Microsoft estava distribuindo durante o evento Microsoft Ignite. Depois disto, eu fiquei sabendo que eles também estão entregando grandes discontos para quem teve o seu …

+
+ + + +
+
+
+
+
+ + + + + + + +
+

Algumas vezes você se depara com a necessidade de monitorar a disponibilidade de um website ou mudanças em seu conteúdo. É claro que temos diversas opções disponíveis no mercado, mas para fins de curiosidade, vamos programar o nosso próprio e ver o que podemos fazer. Primeiramente, tudo que você ver …

+
+ + + +
+
+
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/category/azure.html.gz b/pt/category/azure.html.gz new file mode 100644 index 000000000..8aac8bc88 Binary files /dev/null and b/pt/category/azure.html.gz differ diff --git a/pt/category/firefoxos.html b/pt/category/firefoxos.html new file mode 100644 index 000000000..a89fd2e0b --- /dev/null +++ b/pt/category/firefoxos.html @@ -0,0 +1,304 @@ + + + + + + + + Sipmann - FirefoxOS category + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Desenvolvendo apps para o FirefoxOS (Parte 1)

+
+ +
+
+ +
+

Requisitos mínimos?

+

Para seguir este tutorial você precisará do Nodejs. Utilizaremos ele para automatizar algumas tarefas, como a criação do nosso projeto e até mesmo o empacotamento da app. Estas automatizações se darão pela utilização de algumas aplicações como o Yeoman e o Grunt .

+

Também será necessário o emulador do …

+
+ + + +
+
+
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/category/firefoxos.html.gz b/pt/category/firefoxos.html.gz new file mode 100644 index 000000000..16d8e795f Binary files /dev/null and b/pt/category/firefoxos.html.gz differ diff --git a/pt/category/java.html b/pt/category/java.html new file mode 100644 index 000000000..320bacaed --- /dev/null +++ b/pt/category/java.html @@ -0,0 +1,307 @@ + + + + + + + + Sipmann - Java category + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/category/java.html.gz b/pt/category/java.html.gz new file mode 100644 index 000000000..a93cc4d45 Binary files /dev/null and b/pt/category/java.html.gz differ diff --git a/pt/category/linux.html b/pt/category/linux.html new file mode 100644 index 000000000..5ad7d2788 --- /dev/null +++ b/pt/category/linux.html @@ -0,0 +1,402 @@ + + + + + + + + Sipmann - Linux category + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+ + + + + +
+

Zabbix Running on Low Memory Mode

+
+ +
+
+ +
+

Olá pessoal! Trago hoje outro post sobre Zabbix. Este é sobre aumentar o cache do seu Zabbix Server. É perfeitamente comum (se você roda com as configurações padrões) receber avisos sobre Zabbix value cache running on low memory mode no seu dashboard ou arquivos de log.

+

Zabbix Dashboard alertando sobre problemas de memória +Zabbix Dashboard cache gráfico com 70% utilizado

+

Para resolver, abra o …

+
+ + + +
+
+
+
+
+
+

Zabbix poller processes more than 75%

+
+ +
+
+ +
+

Este é o terceiro post sobre configurações para o Zabbix. Todas as alterações que eu sugiro nestes posts, são baseadas em um servidor com 50+ hosts. Outro problema que pode ocorrer em seu servidor, é o poller de informações ficar sobrecarregado pela quantidade de servidores que ele precisa pegar carga …

+
+ + + +
+
+
+
+
+
+

Zabbix ICMP pinger processes more than 75%

+
+ +
+
+ +
+

Então o seu systema de monitoramento creasceu e o seu Zabbix começou a printar "Zabbix icmp pinger processes more than 75% busy" no seu dashboard.

+

Dashboard do zabbix avisando sobre o erro

+

Tudo que você tem a fazer é abrir o seu arquivo de configuração (/etc/zabbix/zabbix_server.conf) e localizar a tag chamada StartPingers. Ela deve …

+
+ + + +
+
+
+
+
+
+

Zabbix Server Out of Memory

+
+ +
+
+ +
+

Você tem um servidor Zabbix crashando e observando o arquivo de log /var/log/zabbix/zabbix_server.log você localiza a seguinte mensagem referênciando falta de memória?

+
__mem_malloc: skipped 0 asked 24 skip_min 18446744073709551615 skip_max 0
+[file:dbconfig.c,line:94] __zbx_mem_realloc(): out of memory (requested 16 bytes)
+[file:dbconfig.c …

+
+ + + +
+
+
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/category/linux.html.gz b/pt/category/linux.html.gz new file mode 100644 index 000000000..1604992ff Binary files /dev/null and b/pt/category/linux.html.gz differ diff --git a/pt/category/mysql.html b/pt/category/mysql.html new file mode 100644 index 000000000..92df7c3a7 --- /dev/null +++ b/pt/category/mysql.html @@ -0,0 +1,307 @@ + + + + + + + + Sipmann - MySQL category + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/category/mysql.html.gz b/pt/category/mysql.html.gz new file mode 100644 index 000000000..ccb99ef78 Binary files /dev/null and b/pt/category/mysql.html.gz differ diff --git a/pt/category/net.html b/pt/category/net.html new file mode 100644 index 000000000..c6bfd2f98 --- /dev/null +++ b/pt/category/net.html @@ -0,0 +1,348 @@ + + + + + + + + Sipmann - .NET category + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+ + + + + + + +
+

Então, você utiliza Entity Framework Core e geralmente faz o seu selecto da seguinte forma, talvez você está retornando muitos dados.

+
var products = Products
+    .Where(p => p.UnitsInStock > 0)
+    .OrderBy(p => p.ProductName)
+    .ToList()
+
+ +

Rodando a query acima, em uma base de testes você obtem o seguinte resultado, veja quantas …

+
+ + + +
+
+
+
+
+ + + + + +
+

Top Level Statement no C# 9

+
+ +
+
+ +
+

Olá pessoal, venho hoje falar sobre uma novidade que estará disponível na versão 9 do C#. Toda vez que você deseja criar um novo projeto, você sempre tem o mesmo arquivo Main, com a mesma estrutura. Na próxima versão do C# (versão 9), nós teremos uma nova funcionalidade chamada Top …

+
+ + + +
+
+
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/category/net.html.gz b/pt/category/net.html.gz new file mode 100644 index 000000000..49f6b5d19 Binary files /dev/null and b/pt/category/net.html.gz differ diff --git a/pt/category/powershell.html b/pt/category/powershell.html new file mode 100644 index 000000000..f5d8d3b93 --- /dev/null +++ b/pt/category/powershell.html @@ -0,0 +1,379 @@ + + + + + + + + Sipmann - PowerShell category + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+ + + + + + + +
+

Tenho migrado alguns scripts bash que tenho para PowerShell, e chegou a vez de migrar um script de monitoramento de replicação do MySQL. Fica como crédito o script original do Paweł. É um script bem simples onde eu verifico algumas tags resultantes do SHOW SLAVE STATUS\G, são elas. Slave_IO_Running …

+
+ + + +
+
+
+
+
+ + + + + +
+

O poder do PowerShell

+
+ +
+
+ +
+

Como um usuário linux por muito tempo, eu automatizei algumas tarefas com scripts bash e fiquei longe do PowerShell... Voltei a utilizar Windows alguns anos atrás e ainda assim, não dei uma chance ao PS. Mas porque não? Eu fiz alguns scripts para automatizar algumas tarefas em um servidor Protheus …

+
+ + + +
+
+
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/category/powershell.html.gz b/pt/category/powershell.html.gz new file mode 100644 index 000000000..68aca06d6 Binary files /dev/null and b/pt/category/powershell.html.gz differ diff --git a/pt/category/python.html b/pt/category/python.html new file mode 100644 index 000000000..5a79163fb --- /dev/null +++ b/pt/category/python.html @@ -0,0 +1,331 @@ + + + + + + + + Sipmann - Python category + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Menu dinâmico com as apps do django

+
+ +
+
+ +
+

Digamos que sua empresa trabalha com Django desenvolvendo aplicações cujas apps são plugaveis e reutilizáveis. Por que não se aproveitar de um certo padrão de desenvolvimento para desenvolver menus que se modificam de acordo com as apps que estão no projeto? Como o objetivo aqui não é desenvolver uma app …

+
+ + + +
+
+
+
+
+
+

Editando o Admin do Django

+
+ +
+
+ +
+

Este artigo foi re-postado no grupo PythonClub. Vamos falar um pouco sobre como customizar o admin do Django. Primeiramente porque? A resposta é bem simples, quero mostrar algo para o usuário sem que ele precise entrar nas apps e fazer alguma consulta para então tomar alguma ação. Alguns exêmplos para …

+
+ + + +
+
+
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/category/python.html.gz b/pt/category/python.html.gz new file mode 100644 index 000000000..ed486a885 Binary files /dev/null and b/pt/category/python.html.gz differ diff --git a/pt/category/shell.html b/pt/category/shell.html new file mode 100644 index 000000000..6bf61471d --- /dev/null +++ b/pt/category/shell.html @@ -0,0 +1,303 @@ + + + + + + + + Sipmann - Shell category + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Scripts de inicialização no raspberry pi

+
+ +
+
+ +
+

Instalei essa semana o gitea no meu raspberry pi B + e queria iniciar ele no boot... Não sou profundo conhecedor de linux, então, logo não sabia como fazer isto da melhor forma. +As versões atuais do Raspbian utilizam o systemd para gerenciar os serviços e confesso que nunca havia utilizado …

+
+ + + +
+
+
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/category/shell.html.gz b/pt/category/shell.html.gz new file mode 100644 index 000000000..49c79001b Binary files /dev/null and b/pt/category/shell.html.gz differ diff --git a/pt/category/sql-server.html b/pt/category/sql-server.html new file mode 100644 index 000000000..0cd8bad91 --- /dev/null +++ b/pt/category/sql-server.html @@ -0,0 +1,340 @@ + + + + + + + + Sipmann - SQL Server category + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Removendo um usuário de uma base SQL Server

+
+ +
+
+ +
+

O seu cliente lhe pede com urgência para dropar um usuário da sua base MsSQL Server, mas você trava com o seguinte aviso de erro:

+
Error: 15138 The database principal owns a schema in the database, and cannot be dropped.
+
+ +

Se você não possui (ou no momento não consegue acesso …

+
+ + + +
+
+
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/category/sql-server.html.gz b/pt/category/sql-server.html.gz new file mode 100644 index 000000000..ce025bbe8 Binary files /dev/null and b/pt/category/sql-server.html.gz differ diff --git a/pt/category/tools.html b/pt/category/tools.html new file mode 100644 index 000000000..bd07b0e56 --- /dev/null +++ b/pt/category/tools.html @@ -0,0 +1,333 @@ + + + + + + + + Sipmann - Tools category + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Apache Nifi JSON to SQL removendo underline

+
+ +
+
+ +
+

Recentemente eu estava desenvolvendo alguns processos de ETL com o Apache NiFi. Mas após alguns minutos desenhando o meu fluxo, eu vi um comportamento estranho do componente ConvertJSONToSQL, que estava substituindo os underline ('_') do nome de um campo utilizado na condição da SQL (eu estava preparando um UPDATE). Aquilo …

+
+ + + +
+
+
+
+
+
+

Cool Tools

+
+ +
+
+ +
+

Com o passar do tempo você vai "encontrando" - e às vezes até mesmo desenvolvendo - algumas ferramentas que tornam o seu dia a dia como desenvolvedor mais fácil. Abaixo seguem algumas das minhas ferramentas que costumo usar. Ressalto que essa lista será (provavelmente) atualizada com o passar do tempo.

+

+
+ + + +
+
+
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/category/tools.html.gz b/pt/category/tools.html.gz new file mode 100644 index 000000000..9aeb4fcde Binary files /dev/null and b/pt/category/tools.html.gz differ diff --git a/pt/cool-tools.html b/pt/cool-tools.html new file mode 100644 index 000000000..a25d1d362 --- /dev/null +++ b/pt/cool-tools.html @@ -0,0 +1,456 @@ + + + + + + + + Cool Tools - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Cool Tools

+
+ +
+
+ +
+

Com o passar do tempo você vai "encontrando" - e às vezes até mesmo desenvolvendo - algumas ferramentas que tornam o seu dia a dia como desenvolvedor mais fácil. Abaixo seguem algumas das minhas ferramentas que costumo usar. Ressalto que essa lista será (provavelmente) atualizada com o passar do tempo.

+
+

https://www.gitkraken.com

+

Eu gosto muito de usar git, mas às vezes fico cansado de ter que usar só linha de comando, e achei no GitKreaken uma interface muito legal de se usar.

+
+
+

http://paletton.com

+

Toda vez que você vai fazer um novo sistema/site, ou até mesmo trocar o layout de algum já existente, você acaba tendo que montar uma paleta de cores para se utilizar em todo o template.

+
+
+

https://icomoon.io/app/#/select

+

Querendo usar ícones como fontes? Vá aí e gere apenas os arquivos que você vai realmente utilizar e economize alguns kbs.

+
+
+

https://syncthing.net/

+

Se você procura algum meio de sincronizar seus arquivos entre vários pcs e por algum motivo não quer usar um Google Drive ou DropBox, fica aqui a indicação deste cara.

+
+
+

http://sqitch.org/

+

Gerenciamento de versões de um banco de dados pode ser bem complicado e trabalhoso... Manter diversos ambientes (desenvolvimento, homologação, produção) vai dar um trabalho se não utilizar alguma ferramenta. Porque não usar o melhor de gerenciamento de versão (git) e uma ferramenta que se adequa ao que você precisa? sqitch é o cara nessas horas.

+
+
+

http://www.setupmyproject.com/

+

Preparação de projetos java, com frameworks, bibliotecas, nomenclatura, etc... Rende uma economia de tempo grandiosa e já vem tudo pronto :).

+
+
+

https://www.pexels.com/

+

Bom site para imagens free stock. Excelente local para conseguir imagens de alta qualidade.

+
+
+

https://heml.io/

+

"HEML is an open source markup language for building responsive email." Melhor descrição impossível.

+
+
+

https://www.mockapi.io/

+

Desenvolva mocks para testar seu front-end. Eles geram inclusive uma carga de dados para ser utilizado nos seus testes.

+
+
+

https://undraw.co

+

Needing some cool and free ilustrations? Take a look at it.

+
+
+

https://www.audiotool.com/app/

+

Ferramenta para criar sons, musicas e afins

+
+
+

https://app.cloudskew.com/

+

Desenhar projetos de cloud e afins

+
+
+

https://lottiefiles.com/

+

Veja por si mesmo

+
+

+
+ + +
+
+

Traduções:

+
    +
+
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/cool-tools.html.gz b/pt/cool-tools.html.gz new file mode 100644 index 000000000..dca88061a Binary files /dev/null and b/pt/cool-tools.html.gz differ diff --git a/pt/desenvolvendo-app-firefoxos.html b/pt/desenvolvendo-app-firefoxos.html new file mode 100644 index 000000000..f8958e9d4 --- /dev/null +++ b/pt/desenvolvendo-app-firefoxos.html @@ -0,0 +1,445 @@ + + + + + + + + Desenvolvendo apps para o FirefoxOS (Parte 1) - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Desenvolvendo apps para o FirefoxOS (Parte 1)

+
+ +
+
+ +
+

Requisitos mínimos?

+

Para seguir este tutorial você precisará do Nodejs. Utilizaremos ele para automatizar algumas tarefas, como a criação do nosso projeto e até mesmo o empacotamento da app. Estas automatizações se darão pela utilização de algumas aplicações como o Yeoman e o Grunt .

+

Também será necessário o emulador do FirefoxOS, ele roda através do seu navegador Firefox. Para instalá-lo basta ir no menu Ferramentas > Desenvolvedor web > App Manager, nesta tela basta tentar iniciar o emulador, se não possuir um já instalado, você será solicitado a fazê-lo. Neste tutorial irei utilizar a versão 1.4.

+

Preparando o ambiente

+

Tendo o Node instalado, vamos instalar o yeoman e o gerador de app para Firefox OS. Atenção para o parâmetro '-g' no processo de instalação, com ele os seus pacotes serão instalados globalmente, e não só para a pasta em que esta o prompt.

+
npm install -g yo
+npm install -g generator-firefoxos-app
+
+ +

Com ambos os pacotes acima instalados, vamos dar início a criação da app. No seu diretório de projetos ou onde desejar criar a app chama o generator instalado.

+
yo firefoxos-app
+
+ +

Uma vez chamado esse generator, o mesmo irá fazer alguns questionamentos, o primeiro é claro será o nome da sua aplicação, seguido da descrição e o nome do desenvolvedor.

+

Após a execução do generator, você já terá uma estrutura para desenvolvimento pronta, inclusive com um html inicial, com todas as dependências já instaladas. Vale ressaltar agora algumas tarefas disponíveis no Gruntfile.

+
    +
  • Default: Irá gerar o pacote de distribuição
  • +
  • Test: Até a presente versão do generator (0.1.3) este processo irá simplesmente rodar o validador jsHint
  • +
  • Server: Irá disponibilizar na porta 9001 um simples servidor para testar a sua app
  • +
+

Vamos testar a nossa app. Para tal, rode o comando grunt server e acesse no seu navegador localhost:9001 e devemos ver a seguinte app. Caso nenhuma página seja exibida, revise os passos ateriores e verifique se nenhum erro ocorreu.

+

App inicial

+

Vale ressaltar que a sua app toda estará dentro de uma pasta também chamada app. Nela você encontrará os seus arquivos .html, .js, .css e demais. Antes de começarmos a codificar a nossa app, vamos ver como se instala a mesma.

+

Instalando a app

+

Para fins de teste, não é necessário rodar o comando grunt, sendo que ele irá testar o JS e compactar tudo em um arquivo .zip, basta apontar a instalação para a pasta app dentro do seu projeto. "Mas como eu faço isto?".

+

Indo novamente na App Manager, clicando na lateral esquerda, onde indica "Aplicativos", teremos então disponível no inferior da tela duas opções, vamos nos ater a utilizar a primeira (Adicionar aplicativo hospedado).

+

Clicando nesta opção vamos navegar até a pasta da app e clicar selecionada. Pronto.

+

Simples de se instalar, não acha? O Resultado final deve ser semelhante ao abaixo.

+

App inicial

+

Acessando uma API

+

Quando vamos programar algo mais complexo, geralmente vamos utilizar algo como, câmera, rede, lista de contatos, armazenamento e outras possibilidades. Para utilizarmos essas APIs, precisamos - assim como no desenvolvimento para android - especificar para o usuário no momento de instalação. Estes dados de acesso ficam no arquivo manifes.webapp, se você ainda não deu uma olhada neste arquivo, é nele que fica armazenado dados da app, como nome, descrição, versão, localização de ícones e é claro as permissões que a mesma requer.

+

As permissões ficam na propriedade permissions, na forma de "chave" : True. Algumas das apis são:

+
    +
  • câmera
  • +
  • contacts
  • +
  • desktop-notification
  • +
  • storage
  • +
+

Cada permissão vai mudar o tipo de app que você esta desenvolvendo, mas aí eu sugiro ler mais na MDN aqui. Esse é o básico para iniciar no desenvolvimento de app para FirefoxOS. Na parte dois, vou começar a passar um pouco de código.

+
+ + +
+
+

Traduções:

+
    +
+
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/desenvolvendo-app-firefoxos.html.gz b/pt/desenvolvendo-app-firefoxos.html.gz new file mode 100644 index 000000000..0a2e055e5 Binary files /dev/null and b/pt/desenvolvendo-app-firefoxos.html.gz differ diff --git a/pt/drafts/azure-data-fundamentals-certification-80-discount-en.html b/pt/drafts/azure-data-fundamentals-certification-80-discount-en.html new file mode 100644 index 000000000..8cde221e7 --- /dev/null +++ b/pt/drafts/azure-data-fundamentals-certification-80-discount-en.html @@ -0,0 +1,511 @@ + + + + + + + + Azure Data Fundamentals certification with 80% discount - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+ + +
+

Hey folks, if you want to achieve some certification this year, keep an eye open for vouchers. A few months ago, Oracle released a set of free courses with certifications. Now it's Microsoft time. Microsoft is updating they're certifications and we have a voucher of 80% discount using the coupon DP900Norfolk at the checkout of the beta certification DP-900.

+

Be aware that this certification is in beta and the result won't be instantly available as the regular ones. Access the following link and schedule your exam. https://docs.microsoft.com/pt-br/learn/certifications/exams/dp-900.

+

Update: There is a 80% voucher also for https://docs.microsoft.com/en-us/learn/certifications/azure-ai-fundamentals. Voucher: AI900Saratoga

+
+ + +
+
+

Traduções:

+
    +
+
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/drafts/azure-data-fundamentals-certification-80-discount-en.html.gz b/pt/drafts/azure-data-fundamentals-certification-80-discount-en.html.gz new file mode 100644 index 000000000..318e37cb3 Binary files /dev/null and b/pt/drafts/azure-data-fundamentals-certification-80-discount-en.html.gz differ diff --git a/pt/drafts/cloud-not-open-connection-java-mysql-hibernate-en.html b/pt/drafts/cloud-not-open-connection-java-mysql-hibernate-en.html new file mode 100644 index 000000000..b142556bb --- /dev/null +++ b/pt/drafts/cloud-not-open-connection-java-mysql-hibernate-en.html @@ -0,0 +1,474 @@ + + + + + + + + Could not open connection with MySQL and Hibernate - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+ + +
+

Last day I decided to deploy a MySQL Docker image to work with my Java application. I've been using PostgreSQL instead and have no problems at all, but after I moved to MySQL, the app didn't connect anymore with the database and throw some "Could not open connection" at my face, but why? I've tried to connect to it manually and got the same problem.

+

After some research, I found that the true error should be java.sql.SQLException: null, message from server: "Host '172.17.0.4' is not allowed to connect to this MySQL server" but it wasn't showing to me...

+

After all, be aware that with the docker image MySQL:5.7.21 (latest version right now) the root user isn't allowed to remote connect to the database (it's alright, security reasons) and if you still want to do remote connections to it with root there are a few things you can do.

+
    +
  1. Create a user or allow root to access from other IPs.
  2. +
+
#No access to user root on any other IP
+SELECT User, Host FROM mysql.user;
++---------------+-----------+
+| User          | Host      |
++---------------+-----------+
+| healthchecker | localhost |
+| root          | localhost |
++---------------+-----------+
+2 rows in set (0.01 sec)
+
+CREATE USER 'newuser'@'%' IDENTIFIED BY 'password'; #% mean any IP
+GRANT ALL PRIVILEGES ON *.* TO 'newuser'@'%';   #*.* mean database.table ;)
+
+
    +
  1. Use MariaDB instead, witch come (at least on the version 10.2.13) with root allowed to do remote connections and will work like MySQL :)
  2. +
+

I changed to MariaDB as it work without creating user or any changes on the Java code or the docker run command.

+

+
+ + +
+
+

Traduções:

+
    +
+
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/drafts/cloud-not-open-connection-java-mysql-hibernate-en.html.gz b/pt/drafts/cloud-not-open-connection-java-mysql-hibernate-en.html.gz new file mode 100644 index 000000000..5e65c5eb6 Binary files /dev/null and b/pt/drafts/cloud-not-open-connection-java-mysql-hibernate-en.html.gz differ diff --git a/pt/drafts/cloud-not-open-connection-java-mysql-hibernate.html b/pt/drafts/cloud-not-open-connection-java-mysql-hibernate.html new file mode 100644 index 000000000..e36a82056 --- /dev/null +++ b/pt/drafts/cloud-not-open-connection-java-mysql-hibernate.html @@ -0,0 +1,474 @@ + + + + + + + + Could not open connection com MySQL e Hibernate - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+ + +
+

Last day I decided to deploy a MySQL Docker image to work with my Java application. I've been using PostgreSQL instead and have no problems at all, but after I moved to MySQL, the app didn't connect anymore with the database and throw some "Could not open connection" at my face, but why? I've tried to connect to it manually and got the same problem.

+

After some research, I found that the true error should be java.sql.SQLException: null, message from server: "Host '172.17.0.4' is not allowed to connect to this MySQL server" but it wasn't showing to me...

+

After all, be aware that with the docker image MySQL:5.7.21 (latest version right now) the root user isn't allowed to remote connect to the database (it's alright, security reasons) and if you still want to do remote connections to it with root there are a few things you can do.

+
    +
  1. Create a user or allow root to access from other IPs.
  2. +
+
#No access to user root on any other IP
+SELECT User, Host FROM mysql.user;
++---------------+-----------+
+| User          | Host      |
++---------------+-----------+
+| healthchecker | localhost |
+| root          | localhost |
++---------------+-----------+
+2 rows in set (0.01 sec)
+
+CREATE USER 'newuser'@'%' IDENTIFIED BY 'password'; #% mean any IP
+GRANT ALL PRIVILEGES ON *.* TO 'newuser'@'%';   #*.* mean database.table ;)
+
+
    +
  1. Use MariaDB instead, witch come (at least on the version 10.2.13) with root allowed to do remote connections and will work like MySQL :)
  2. +
+

I changed to MariaDB as it work without creating user or any changes on the Java code or the docker run command.

+

+
+ + +
+
+

Traduções:

+
    +
+
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/drafts/cloud-not-open-connection-java-mysql-hibernate.html.gz b/pt/drafts/cloud-not-open-connection-java-mysql-hibernate.html.gz new file mode 100644 index 000000000..ebfd91c7d Binary files /dev/null and b/pt/drafts/cloud-not-open-connection-java-mysql-hibernate.html.gz differ diff --git a/pt/drafts/connecting_to_database_through_ssh-en.html b/pt/drafts/connecting_to_database_through_ssh-en.html new file mode 100644 index 000000000..77a0007c6 --- /dev/null +++ b/pt/drafts/connecting_to_database_through_ssh-en.html @@ -0,0 +1,419 @@ + + + + + + + + Connecting to a database through SSH - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Connecting to a database through SSH

+
+ +
+
+ +
+

If someday, for some reason, you need to establish a connection with a database which is behind a firewall and you only have SSH access on that server (and you don't want to use a CLI) you can do an SSH tunnel. It's pretty simple, bellow has a sample of how to allow connections to a remote Firebird database.

+
ssh -L 3051:192.168.1.9:3050 username@192.168.1.9
+
+

The -L parameter tells to SSH do a local port forwarding on local port 3051 to remote port 3050. You can use it to a connection with many services, not just databases.

+

You can do the reverse kind of tunnel, forward connections from the host to your local machine, you just have to change the parameter form "-L" to "-R" and the port order is inverted, first come the port where the server will listen and after your localhost port. This remote port forwarding must be enabled on the server. Look for GatewayPorts at the ssh config file.

+
ssh -R 3050:localhost:3050 username@192.168.1.9
+
+

Why whould you need something like that?? Let's say you want to share a localhost site/database with a friend, but your internet connection don't allow you to expose any port but you have access to a remote server witch can do that. Problem solved ;).

+

+
+ + +
+
+

Traduções:

+
    +
+
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/drafts/connecting_to_database_through_ssh-en.html.gz b/pt/drafts/connecting_to_database_through_ssh-en.html.gz new file mode 100644 index 000000000..1aa568f7f Binary files /dev/null and b/pt/drafts/connecting_to_database_through_ssh-en.html.gz differ diff --git a/pt/drafts/flutter_with_firebase_auth_crashing-en.html b/pt/drafts/flutter_with_firebase_auth_crashing-en.html new file mode 100644 index 000000000..234239776 --- /dev/null +++ b/pt/drafts/flutter_with_firebase_auth_crashing-en.html @@ -0,0 +1,433 @@ + + + + + + + + Flutter + firebase auth crashing - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Flutter + firebase auth crashing

+
+ +
+
+ +
+

Hey Folks, recently I've started learning Flutter and right after a TODO List, I tried a Firebase integration. But as soon as I started setting the dependencies, my app stopped opening... just a crash. After a few logs digging, I've found the following log.

+
AndroidRuntime: FATAL EXCEPTION: main
+AndroidRuntime: Process: com.example.diadocasal, PID: 13672
+AndroidRuntime: java.lang.NoClassDefFoundError: Failed resolution of: Landroid/support/v4/util/ArrayMap;
+AndroidRuntime:     at com.google.android.gms.internal.measurement.zzca.<clinit>(Unknown Source:60)
+AndroidRuntime:     at com.google.android.gms.internal.measurement.zzcm.zzr(Unknown Source:7)
+AndroidRuntime:     at com.google.android.gms.measurement.internal.zzfj.<init>(Unknown Source:23)
+
+ +

Notice the "NoClassDefFound" of an ArrayMap. To solve that I did the following changes to the files:

+
//build.gradle file
+ ext.kotlin_version = '1.3.20'
+[...]
+ dependencies {
+        classpath 'com.android.tools.build:gradle:3.3.0' // gradle version
+
+ +
;gradle.properties file
+org.gradle.jvmargs=-Xmx1536M ;mine have just this line at first
+android.useAndroidX=true ; uses androidX instead of the default support library
+android.enableJetifier=true ; uses jetpack libraries
+android.enableR8=true ; the new code shriker
+
+ +

After that, voilà, app up and running.

+
+ + +
+
+

Traduções:

+
    +
+
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/drafts/flutter_with_firebase_auth_crashing-en.html.gz b/pt/drafts/flutter_with_firebase_auth_crashing-en.html.gz new file mode 100644 index 000000000..605189e1d Binary files /dev/null and b/pt/drafts/flutter_with_firebase_auth_crashing-en.html.gz differ diff --git a/pt/drafts/limiting-connection-resources-sql-server-en.html b/pt/drafts/limiting-connection-resources-sql-server-en.html new file mode 100644 index 000000000..46e1997c1 --- /dev/null +++ b/pt/drafts/limiting-connection-resources-sql-server-en.html @@ -0,0 +1,532 @@ + + + + + + + + Limiting Connection Resources on SQL Server - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Limiting Connection Resources on SQL Server

+
+ +
+
+ +
+

Have you ever suffered from a slow SQLServer database? Someone love to run that heavy query in the database? Resource Governor to the rescue. You can set a few rules on how users (connections actually) will use the server/database resources based on a few things.

+

First things first, if you don't have DAC enabled, enable it now. Dealing with resource governor can lock you out of the database and leave you without action (almost... you can start the server with -c -m -f).

+

Now to understand how Resource Governor works, we have a few keywords resource pool, workload group e Classifier Function.

+

Pool Sample

+

Resource Pool

+

First, we have the Resource Pool, with is the bigger resource group that we have the ability to manage. With it, we can set a few things like: MIN_CPU_PERCENT, MAX_CPU_PERCENT, MIN_MEMORY_PERCENT, MAX_MEMORY_PERCENT, MIN_IOPS_PER_VOLUME, and MAX_IOPS_PER_VOLUME.

+

Be aware that the MAX_CPU_PERCENT will just "works" when there is another connection with a higher priority, otherwise it will use what is available. Let's create a pool.

+
CREATE RESOURCE POOL [SpreadSheet]
+WITH (
+    MIN_CPU_PERCENT=0,
+    MAX_CPU_PERCENT=20,
+    MIN_MEMORY_PERCENT=0,
+    MAX_MEMORY_PERCENT=20
+);
+
+ +

## Workload Group

+

Then we have a workload group that "works" inside a pool, so you can have another granularity on how you can split your resources. Again, we have a few options: IMPORTANCE, REQUEST_MAX_CPU_TIME_SEC, REQUEST_MAX_MEMORY_GRANT_PERCENT, GROUP_MAX_REQUESTS.

+

The IMPORTANCE set guesses what... the importance of that workload inside the pool, you can set LOW, MEDIUM, HIGH. GROUP_MAX_REQUESTS sets how many requests can run at the same time inside that workload (0 will set as NO LIMIT)

+
CREATE WORKLOAD GROUP [DepartmentA] 
+WITH (
+    GROUP_MAX_REQUESTS=2,
+    IMPORTANCE=LOW,
+    REQUEST_MAX_CPU_TIME_SEC=10, -- Time running/using CPU
+    REQUEST_MAX_MEMORY_GRANT_PERCENT=15
+) USING [SpreadSheet]; -- pool name here
+
+ +

Classifier Function

+

This is where everything begins... This is the entry point where you should set the group name. It's a function that will run for every new connection so be aware that if your function runs lots of queries or some heavy stuff... that time will be added to the connection handshake. If the function returns NULL or a group name that doesn't exist, the 'default' group will be used... Yes, there is a default workload group where everything runs where there's no classifier.

+
CREATE FUNCTION fnClassWorkloadGovernor() 
+RETURNS SYSNAME WITH SCHEMABINDING 
+AS 
+BEGIN 
+    IF APP_NAME() LIKE '%Excel%'
+        RETURN 'DepartmentA'
+
+    IF HOST_NAME() LIKE '%THAT_MACHINE_OR_APP_SERVER%'
+        RETURN 'LowPriority'
+
+    RETURN NULL
+END
+GO
+
+ALTER RESOURCE GOVERNOR WITH (CLASSIFIER_FUNCTION=dbo.fnClassWorkloadGovernor);
+ALTER RESOURCE GOVERNOR RECONFIGURE;
+
+ +

There you go... now you have a fully working resource governor, but look out that If you want to delete that classifier function, first you have to remove it from the resource governor (look the SCHEMABINDING at the create up there).

+

To disable Resource Governor

+
ALTER RESOURCE GOVERNOR WITH (CLASSIFIER_FUNCTION=null)
+ALTER RESOURCE GOVERNOR RECONFIGURE
+
+ALTER RESOURCE GOVERNOR DISABLE
+GO
+

+
+ + +
+
+

Traduções:

+
    +
+
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/drafts/limiting-connection-resources-sql-server-en.html.gz b/pt/drafts/limiting-connection-resources-sql-server-en.html.gz new file mode 100644 index 000000000..aaf272edb Binary files /dev/null and b/pt/drafts/limiting-connection-resources-sql-server-en.html.gz differ diff --git a/pt/drafts/linux-external-display-with-disper-en.html b/pt/drafts/linux-external-display-with-disper-en.html new file mode 100644 index 000000000..277570c22 --- /dev/null +++ b/pt/drafts/linux-external-display-with-disper-en.html @@ -0,0 +1,420 @@ + + + + + + + + Change display settings on linux with Disper - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Change display settings on linux with Disper

+
+ +
+
+ +
+

From time to time, I change the Linux distro on my laptop or just do a fresh install on it. And once in a while, have random problems with external displays. It can be something really "simple" like don't detecting the external monitor or something crazy like the image below.

+Display bug +

As you can see at the image, the mint detected the display but mirrored it in a crazy way that works but doesn't at the same time. If you try anything and doesn't get working, or just wanna skip the whole job of configuring complexes text files, give a try to Disper. Download the latest version. +Extract it on any folder, and make install it (on the extracted folder).

+
make install
+
+

After that, you can start using it... There are a few options that will serve you well.

+
disper -e #extend your display
+
+
disper -c #clone your display
+
+
disper -s #only your external display
+
+

+
+ + +
+
+

Traduções:

+
    +
+
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/drafts/linux-external-display-with-disper-en.html.gz b/pt/drafts/linux-external-display-with-disper-en.html.gz new file mode 100644 index 000000000..1b043e31a Binary files /dev/null and b/pt/drafts/linux-external-display-with-disper-en.html.gz differ diff --git a/pt/drafts/microservices_nodejs_express_rabbitmq_part_1-en.html b/pt/drafts/microservices_nodejs_express_rabbitmq_part_1-en.html new file mode 100644 index 000000000..051889a23 --- /dev/null +++ b/pt/drafts/microservices_nodejs_express_rabbitmq_part_1-en.html @@ -0,0 +1,476 @@ + + + + + + + + Microservices with NodeJS, Express.js and RabbitMQ Part 1 - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+ + +
+

This is the first part of a microservices development series. The service will consist of the bellow architecture, where we will expose an image optimizer service that will forward the request to a RabbitMQ queue and answer with the bytecode of the optimized image. It shouldn't be a long series so let's see what we can do.

+Service architecture +

Let's get our environment working. First, we'll need to install the libraries that we'll use.

+

Create a dir and initialize the nodejs application inside it (npm init) and then let's install the deps.

+
    +
  • amqplib - AMQP lib to interact with rabbitmq
  • +
  • express - Do our basic rest API
  • +
  • express-fileupload - easy file upload parser
  • +
  • imagemin and imagemin-pngquant - our image compacter
  • +
+
npm install --save express amqplib express-fileupload imagemin imagemin-pngquant
+
+

Now let's write the entry points for our service, we'll have two basic entry points. The path / that will have a welcome message, the second path will be /upload and this is the one that will handle the image and produce a job for our workers.

+
const express = require('express');
+const fileUpload = require('express-fileupload');
+
+//Instantiate the app and set the fileupload parser to manage files
+const app = express();
+app.use(fileUpload());
+
+//Our index entry point
+app.get('/', (req, res) => res.send('Hello From ImageCompacter service'));
+
+//The path that will handle the image file and throw them to the queue
+app.post('/upload', (req, res) => {
+    //With express-fileupload we can grab the files like this
+    let img = req.files.image; //"image" is the name of the input
+
+    res.send('Not ready yet');
+});
+
+//Finally start the app with the given port number
+app.listen(4000, () => console.log('Example app listening on port 4000!'));
+
+

Let's check if it works, run the service with node.

+
node index.js
+Example app listening on port 4000!
+
+

Open the browser and check if it prints our hello message when accessing localhost:4000. Works? Greate. Now let's work with the image and see how we do it. To optimize our image, we'll use the library imagemin and imagemin-pngquant, it will be that simple for now, we'll work with rabbitmq latter.

+
const imagemin = require('imagemin');
+const imageminPngquant = require('imagemin-pngquant');
+//...
+
+//The path that will handle the image file and throw them to the queue
+app.post('/upload', (req, res) => {
+    let img = req.files.image; //"image" is the name of the input
+
+            imagemin.buffer(img.data, {
+        plugins: [imageminPngquant()]
+    })
+    .then(out => {
+        res.write(out,'binary');
+        res.end(null, 'binary');
+    });
+});
+
+    //...
+
+

Use Postman to test the request. To see if it will work, make a request to http://localhost:4000/upload with a formdata with a file. Select the "send and Download" instead of "Send" and you should have an image after that. Bellow an image of how your postman should be.

+Postman +

That's it for today, next week we'll change our code to use RabbitMQ.

+

+
+ + +
+
+

Traduções:

+
    +
+
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/drafts/microservices_nodejs_express_rabbitmq_part_1-en.html.gz b/pt/drafts/microservices_nodejs_express_rabbitmq_part_1-en.html.gz new file mode 100644 index 000000000..35030b992 Binary files /dev/null and b/pt/drafts/microservices_nodejs_express_rabbitmq_part_1-en.html.gz differ diff --git a/pt/drafts/microservices_nodejs_express_rabbitmq_part_2-en.html b/pt/drafts/microservices_nodejs_express_rabbitmq_part_2-en.html new file mode 100644 index 000000000..3a0354617 --- /dev/null +++ b/pt/drafts/microservices_nodejs_express_rabbitmq_part_2-en.html @@ -0,0 +1,507 @@ + + + + + + + + Microservices with NodeJS, Express.js and RabbitMQ Part 2 - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+ + +
+

If you haven't read the part 1 go ahead and read it... It can be useful :). Or if for some reason you want to start now, you can grab the project where we stopped here and get along. On this part, we'll implement the RabbitMQ queue and see how we can get the best of our app and server with that.

+

Before we began coding, let's understand why we are going to use RabbitMQ if what we have now works? If you check again, you'll see how long it takes to answer the request with the optimized image. It takes a few seconds, so imagine an online service with thousands of request to optimize images (like TinyPNG) how long is it gonna take to answer every request? How much of your server is it gonna take? With only one service running, probably the server will crash.

+

With a queue, we can schedule the requests so we can use the amount of memory and processor that our server has, without taking more than we can. It's better to take a few seconds to answer the request then throw some error to the user. Want more? With RabbitMQ we can see how the queue is doing and we can add more consumers (workers) to it and get things done quicker and distribute the job.

+

First of all, we need an up and running Rabbit server, for the sake of simplicity, I'll use a Docker container with it inside.

+
docker run -d --name rabbit -p 5672:5672 -p 8080:15672 rabbitmq:3-management
+
+

You can see that we're running the rabbitmq:3-management image, which provides us a web interface to see how things are going. After that, if you look at our code you'll see that all the job is made at the '/upload' route, and that's what we'll change.

+

First, we need to understand what we need from RabbitMQ. We need something that, we send an image to a queue and get an optimized image back from that. There is a name for that, is RPC (remote procedure call) and there are two ways of doing this with rabbit. Both the ways you can see on their tutorial page. We'll use the approach that uses a global channel whose id is randomly generated (you'll use the name 'amq.rabbitmq.reply-to' but the rabbit will do the job).

+

Let's start importing the library, defining a few variables and defining a init function that will establish a connection with the rabbit server and create our RPC queue. The RPC queue it's where we'll receive the answer from the consumer (our worker).

+
//import the library
+const amqplib = require('amqplib');
+
+//queue channel
+let channel = null;
+//queue name
+const QUEUE = 'optimizeimg';
+
+//...
+
+function init() {
+    return require('amqplib').connect('amqp://localhost')
+        .then(conn => conn.createChannel())
+        .then(ch => {
+            channel = ch;
+
+            //this queue is a "Direct reply-to" read more at the docs
+            //When some msg comes in, we "emit" a message to the proper "correlationId" listener
+            ch.consume('amq.rabbitmq.reply-to', msg => eventEmitter.emit(msg.properties.correlationId, msg.content), {noAck: true});
+        });
+}
+
+//Random id generator
+function randomid() {
+    return new Date().getTime().toString() + Math.random().toString() + Math.random().toString();
+}
+
+app.post('/upload', (req, res) => {
+    let img = req.files.image;
+
+    let id = randomid();
+
+    //Event listener that will fire when the proper randomid is provided
+    eventEmitter.once(id, msg => {
+        res.write(msg, 'binary');
+        res.end(null, 'binary');
+    });
+
+    //Checks if the queue exists, and create it if needed.
+    channel.assertQueue(QUEUE)
+        //Sent the buffered img to the queue with the ID and the responseQueue
+        .then(() => channel.sendToQueue(QUEUE, img.data, {correlationId:id, replyTo: 'amq.rabbitmq.reply-to'}));
+
+});
+
+//Finally start the app with the given port number
+//now we initialize the rabbitmq connection before start the server
+init()
+    .then(() => app.listen(4000, () => console.log('Example app listening on port 4000!')))
+    .catch(err=>console.error(err));
+
+

Ok, now we have our server code rewritten so let's see our worker code. Create a file named 'worker.js' and let's see how it's gonna be. It's really simple. You initialize a connection with RabbitMQ too, create a channel, check if the queue exists and start watching for incoming messages. When an image arrives, we do the job with it and send back to the "replyTo" queue the optimized image for the proper sender (correlationId). In the end, we do an acknowledge of the message so it get's out from the queue.

+
const imagemin = require('imagemin');
+const imageminPngquant = require('imagemin-pngquant');
+
+let channel = null;
+const QUEUE = 'imgqueue';
+
+require('amqplib').connect('amqp://localhost')
+.then(conn =>conn.createChannel())
+.then(ch => {
+    ch.assertQueue(QUEUE)
+    .then(() => {
+        //Watch incomming messages
+        ch.consume(QUEUE, msg => {
+            imagemin.buffer(msg.content, {
+                plugins: [imageminPngquant()]
+            })
+            .then(out => {
+                //Send back to the sender (replyTo) queue and give the correlationId back
+                //so we can emit the event.
+                ch.sendToQueue(msg.properties.replyTo, out, {
+                    correlationId: msg.properties.correlationId
+                });
+
+                //Acknowledge the job done with the message.
+                ch.ack(msg);
+            });
+        });
+    });
+});
+
+

The key points here are. Open just one connection to the hole server. You CAN create one channel for every request that you receive, but it can take some time if you have a really big cluster of RabbitMQ. It was a quick tutorial, but I hope that it was able to clear a few questions that you might have when working with rabbit and express.

+

+
+ + +
+
+

Traduções:

+
    +
+
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/drafts/microservices_nodejs_express_rabbitmq_part_2-en.html.gz b/pt/drafts/microservices_nodejs_express_rabbitmq_part_2-en.html.gz new file mode 100644 index 000000000..244f69c5a Binary files /dev/null and b/pt/drafts/microservices_nodejs_express_rabbitmq_part_2-en.html.gz differ diff --git a/pt/drafts/my-azure-data-fundamentals-certification.html b/pt/drafts/my-azure-data-fundamentals-certification.html new file mode 100644 index 000000000..d5729a643 --- /dev/null +++ b/pt/drafts/my-azure-data-fundamentals-certification.html @@ -0,0 +1,528 @@ + + + + + + + + My Experience with Azure Data Fundamentals certification - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+ + +
+

E aí pessoal, tudo bom?

+

Bom, este ano tem sido um pouco estranho, não é? E para tentar ajudar como possível, algumas empresas tem oferido vouchers e descontos em ferramentas, cursos, certificações e afins... Bom aproveitei uma demanda e uni com a oportunidade e resolvi iniciar algumas certificações. Mais no início do ano consegui a certificação de Oracle Cloud Infrastructure Foundations e agora tirei a Azure Data Fundamentas (DP-900). Fiz a prova no dia 20/12/2020 e bom, passei. Vou deixar aqui um resuminho de o que caiu (dentro do permitido) e como se preparar.

+

Azure Data Fundamentals Certification Badge

+

A prova da DP-900 visa validar conhecimentos básicos sobre os serviços que envolvem dados e como os mesmos são tratados na Azure. Assim como ela, existem outras próvas que são consideradas de iniciação nas certificações, entre elas a mais conhecida a AZ-900 que valida os conhecimentos gerais sobre Cloud e como adiministrar (de forma básica) uma cloud na Azure.

+

Por serem avalizações de iniciação, elas não são pré-requisito para nenhuma outra certificação, mas são legais para ter uma base de como funcionam as certificações em si. A prova em sí, é relativamente fácil, principalmente para quem já trabalha de alguma forma com dados na Azure. Se você não trabalha ativamente ainda, não se preocupe, pois, como falei, a prova é bem simples e visa dar uma inicialização em quem está buscando entrar na carreira.

+

Se você não tem vivência (ou mesmo se você tiver, mas quer reforçar o conhecimento) existem algumas formas de aprender o conteúdo da prova. Eu pessoalmente só utilizei o learning path que a Microsoft libera gratuitamente na sua plataforma e o mesmo foi suficiente para passar, mas existem cursos preparatórios na Udemy e até mesmo alguns livros na Amazon (não localizei sobre a DP-900 especificamente, mas existem outros que possuem abordagem aproximada). Abaixo deixo alguns links para você seguir e ler mais sobre a prova.

+

Detalhes sobre a certificação e learning path (mais a baixo na página)

+

Detalhamento sobre a certifição

+

Distribuição da prova

+
    Skills measured
+    The content of this exam will be updated on January 27, 2021. Please download the exam skills outline below to see what will be changing.
+    Describe core data concepts (15-20%)
+    Describe how to work with relational data on Azure (25-30%)
+    Describe how to work with non-relational data on Azure (25-30%)
+    Describe an analytics workload on Azure (25-30%)
+
+ +

Bom, dito o básico sobre a certificação, vamos a alguns detalhes da prova. Mas antes ATENÇÃO!!!! Iste é o meu ponto de vista sobre a prova, a sua pode ser diferente em alguns aspectos e o que pareceu difícil para mim, pode ser extremamente fácil para você. Então ressalto que procure seguir o learning path que vai conseguir. Fiz a prova on-line (é claro) e foram 49 questões. Os tópicos estavam bem balanceados de acordo com a distribuição citada acima e na verdade, até estranhei a simplicidade com a qual as questões foram tratadas.

+

Os tópicos que mais caíram no meu caso (lembrando, muda de caso para caso) foram questões voltadas aos diferentes tipos de serviços voltados a dados que a Azure oferece focando desde processos de extração, transformação e carga de dados utilizando diferentes serviços. Caíram poucas questões sobre base de dados em si (seja os tipos, manutenção e funções) e o pouco que caiu, quem possui um conhecimento inicial em base de dados consegue se virar tranquilamente.

+

Bom, acho que é isto. Se você está pensando em fazer esta prova, só posso reforçar... Estude o learning path que deve ser o suficiente, mas se você conseguir alguma experiência ela será bem vinda.

+
+ + +
+
+

Traduções:

+ +
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/drafts/my-azure-data-fundamentals-certification.html.gz b/pt/drafts/my-azure-data-fundamentals-certification.html.gz new file mode 100644 index 000000000..b19f461ce Binary files /dev/null and b/pt/drafts/my-azure-data-fundamentals-certification.html.gz differ diff --git a/pt/drafts/now_posting_on_grepora-en.html b/pt/drafts/now_posting_on_grepora-en.html new file mode 100644 index 000000000..48af4c5f4 --- /dev/null +++ b/pt/drafts/now_posting_on_grepora-en.html @@ -0,0 +1,406 @@ + + + + + + + + Now posting on Grepora - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Now posting on Grepora

+
+ +
+
+ +
+

A few weeks ago I started posting at Grepora blog. If you like or are looking for some Oracle related stuff, Grepora it's a good place to go and spend a time reading :). From time to time I'll be posting there, it doesn't mean that this blog will be closed or anything like that, but probably this one will be more focused on Front-end stuff, a few tricks with linux and a lil less with Java.

+

+
+ + +
+
+

Traduções:

+
    +
+
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/drafts/now_posting_on_grepora-en.html.gz b/pt/drafts/now_posting_on_grepora-en.html.gz new file mode 100644 index 000000000..23289a6a3 Binary files /dev/null and b/pt/drafts/now_posting_on_grepora-en.html.gz differ diff --git a/pt/drafts/pages/businesscard-en.html b/pt/drafts/pages/businesscard-en.html new file mode 100644 index 000000000..9e10f3944 --- /dev/null +++ b/pt/drafts/pages/businesscard-en.html @@ -0,0 +1,304 @@ + + + + + + + + businesscard - Sipmann + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+

businesscard

+ +
+

Todo

+
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/drafts/pages/businesscard-en.html.gz b/pt/drafts/pages/businesscard-en.html.gz new file mode 100644 index 000000000..9b20e3559 Binary files /dev/null and b/pt/drafts/pages/businesscard-en.html.gz differ diff --git a/pt/drafts/pages/services-en.html b/pt/drafts/pages/services-en.html new file mode 100644 index 000000000..330921319 --- /dev/null +++ b/pt/drafts/pages/services-en.html @@ -0,0 +1,304 @@ + + + + + + + + Services - Sipmann + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+

Services

+ +
+

Testing

+
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/drafts/pages/services-en.html.gz b/pt/drafts/pages/services-en.html.gz new file mode 100644 index 000000000..4781f8e19 Binary files /dev/null and b/pt/drafts/pages/services-en.html.gz differ diff --git a/pt/drafts/pages/servicos.html b/pt/drafts/pages/servicos.html new file mode 100644 index 000000000..2bab16151 --- /dev/null +++ b/pt/drafts/pages/servicos.html @@ -0,0 +1,304 @@ + + + + + + + + Serviços - Sipmann + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+

Serviços

+ +
+

Testes

+
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/drafts/pages/servicos.html.gz b/pt/drafts/pages/servicos.html.gz new file mode 100644 index 000000000..1563f1b85 Binary files /dev/null and b/pt/drafts/pages/servicos.html.gz differ diff --git a/pt/drafts/reading-files-java-readAllBytes-outofmemory-en.html b/pt/drafts/reading-files-java-readAllBytes-outofmemory-en.html new file mode 100644 index 000000000..98e1940bf --- /dev/null +++ b/pt/drafts/reading-files-java-readAllBytes-outofmemory-en.html @@ -0,0 +1,482 @@ + + + + + + + + Java - Files.readAllBytes throws OutOfMemory - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Java - Files.readAllBytes throws OutOfMemory

+
+ +
+
+ +
+

When you need to interact with files, there's the possibility to read all bytes from the file with Files.readAllBytes. But be aware of the kinds of files your application will deal with because the Java API files have a limit for the buffer that is defined as Integer.MAX_VALUE as you can see above or at the OpenJDK sources.

+
public static byte[] readAllBytes(Path path) throws IOException {
+    try (FileChannel fc = FileChannel.open(path)) {
+        long size = fc.size();
+        if (size > (long)Integer.MAX_VALUE)
+            throw new OutOfMemoryError("Required array size too large");
+
+        byte[] arr = new byte[(int)size];
+        ByteBuffer bb = ByteBuffer.wrap(arr);
+        while (bb.hasRemaining()) {
+            if (fc.read(bb) < 0) {
+                // truncated
+                break;
+            }
+        }
+
+        int nread = bb.position();
+        return (nread == size) ? arr : Arrays.copyOf(arr, nread);
+    }
+}
+
+

With that in mind, check if isn't better read chunks of bytes e work with that slice in exchange of loading the whole file into the memory ;). Above a simple example of how you can read chunks of bytes from the file.

+
byte[] buffer = new byte[1024];
+FileInputStream in = new FileInputStream(file);
+int rc = in.read(buffer);
+while (rc != -1)
+{
+    //crazy stuff here with buffer
+    rc = in.read(buffer);
+}
+
+

+
+ + +
+
+

Traduções:

+
    +
+
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/drafts/reading-files-java-readAllBytes-outofmemory-en.html.gz b/pt/drafts/reading-files-java-readAllBytes-outofmemory-en.html.gz new file mode 100644 index 000000000..c88bcf611 Binary files /dev/null and b/pt/drafts/reading-files-java-readAllBytes-outofmemory-en.html.gz differ diff --git a/pt/drafts/scaffolding_react_app_with_parcel_yeoman-en.html b/pt/drafts/scaffolding_react_app_with_parcel_yeoman-en.html new file mode 100644 index 000000000..d8e842ddd --- /dev/null +++ b/pt/drafts/scaffolding_react_app_with_parcel_yeoman-en.html @@ -0,0 +1,476 @@ + + + + + + + + Scaffolding a React app with Parcel and Yeoman - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+ + +
+

Since Parcel JS arrived, I've been using it a lot as an awesome alternative for WebPack. Webpack isn't bad but IMO it's too complex for the job and parcel do the same (at least the basic) with almost zero configuration. But if you need to create many apps (like a react app) over and over again, it get's a lil boring following the basic steps.

+
npm init -y
+npm install --save react
+npm install --save react-dom
+npm install --save-dev parcel-bundler
+npm install --save-dev babel-preset-env
+npm install --save-dev babel-preset-react
+
+#create .babelrc file
+#create html, css, jsx files
+
+parcel index.html
+
+

It's not a hard job, a simple shell script do the job, but what if you need some IFs when creating the app, or even change a few things at the package.json? A shell script still does the job, but come on... There is a better way. Yeoman is here for you. I've already talked about it on another post (Portuguese post).

+

Straight to the point, I've released a Yeoman generator to get the things a lil quicker. The name is generator-parcel-react and it still lacks a few things that I will deal with soon. It's pretty simple to use it.

+
#First time only
+npm install -g yo
+npm install -g generator-parcel-react
+
+#every time you create a new app
+yo parcel-react
+
+

And that's it. Right now you can scaffold and app with React, SASS and React Router. Hope you like it and feel free to ask new features.

+

+
+ + +
+
+

Traduções:

+
    +
+
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/drafts/scaffolding_react_app_with_parcel_yeoman-en.html.gz b/pt/drafts/scaffolding_react_app_with_parcel_yeoman-en.html.gz new file mode 100644 index 000000000..2459eeec4 Binary files /dev/null and b/pt/drafts/scaffolding_react_app_with_parcel_yeoman-en.html.gz differ diff --git a/pt/drafts/schedule-blog-post-with-powershell-and-pelican-en.html b/pt/drafts/schedule-blog-post-with-powershell-and-pelican-en.html new file mode 100644 index 000000000..dfae704cc --- /dev/null +++ b/pt/drafts/schedule-blog-post-with-powershell-and-pelican-en.html @@ -0,0 +1,516 @@ + + + + + + + + Scheduling blog posts with Powershell and Pelican - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Scheduling blog posts with Powershell and Pelican

+
+ +
+
+ +
+

Hy folks, first time posting here on dev.to :). Recently I've been migrating some of my scripts from bash to PowerShell and I thought that would be a good time to code an automation script to publish posts on my personal blog. I host my blog with Github Pages and I use Pelican as a static site generator. The main problem I have with this toolkit, is the lack of scheduling posts. For those who are new to Pelican, the post system is similar to dev.to, we write the posts using Markdown and we have a Status tag to tell when the post is a draft or not.

+

The main idea of my script is, run through the Markdown files an check those who have Draft as status. Once I found any post, I start getting some info like the Date and the Slug. The Date part is a little tricky because we need to find the line, split the text and then parse it to do date comparisons. If the post date is lower then the current timespan I replace the Status: Draft tag and save the file. After that all we have to do is commit to git and let it go.

+
$postsPath = "E:\projetos\sipmann.github.io\content\";
+$files = Get-ChildItem $postsPath -File -Filter *.md
+
+<# Get the current datetime so we can compare with the psot date #>
+$now = Get-Date
+
+<# Set the current location, with this we can work with the git commands #>
+Set-Location $postsPath
+
+foreach($file in $files) {
+
+    <# Get's only posts with draft status #>
+    $isDraft = Get-Content ($postsPath + $file) | Where-Object { $_ -ccontains "Status: Draft" }
+
+    if ($isDraft) {
+
+        <# First we find the line with the date, then we get only the datetime and then parse it #>
+        $pubDate = [datetime]::parseexact(((Get-Content ($postsPath + $file) | Where-Object { $_ -Match "^Date:*" }) -split '\s+', 2)[1], 'yyyy-MM-dd HH:mm', $null)
+
+        <# TODO: Maybe call google and bing api to submit a new url #>
+        $slug = ((Get-Content ($postsPath + $file) | Where-Object { $_ -Match "^Slug:*" }) -split '\s+', 2)[1]
+
+        if ($now -ge $pubDate) {
+
+            <# Sets the content without the Draft status #>
+            ((Get-Content ($postsPath + $file)) -replace 'Status: Draft', '') | Set-Content ($postsPath + $file)
+
+            git add .
+            git commit -m ("New scheduled post: " + $file)
+            git push origin master
+        }
+    }
+}
+
+ +

Hope you find the script useful, and if you are interested in the other scripts I'm making with PowerShell, take a look at my github repo, still lacks many of my scripts, but it's there where I'll keep them updated. See ya.

+
+ + +
+
+

Traduções:

+
    +
+
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/drafts/schedule-blog-post-with-powershell-and-pelican-en.html.gz b/pt/drafts/schedule-blog-post-with-powershell-and-pelican-en.html.gz new file mode 100644 index 000000000..42c37c488 Binary files /dev/null and b/pt/drafts/schedule-blog-post-with-powershell-and-pelican-en.html.gz differ diff --git a/pt/drafts/using_git_hooks_easy_your_life-en.html b/pt/drafts/using_git_hooks_easy_your_life-en.html new file mode 100644 index 000000000..f6b9ff916 --- /dev/null +++ b/pt/drafts/using_git_hooks_easy_your_life-en.html @@ -0,0 +1,543 @@ + + + + + + + + Using git hooks to easy your life - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Using git hooks to easy your life

+
+ +
+
+ +
+

Hey folks, it's been a time since my last post. In the meantime, I moved to another state, changed job, and started learning new kinds of stuff. Today I would like to share one thing that I usually do with my small git projects. Git has many cool features, git hooks were one of them. I'll talk about the pre-commit hook today.

+

Let's say that, for some reason, you don't have a CI tool/server running after every commit and you want to enforce that every developer runs the tests before every commit? Git pre-commit to the rescue. You can code the hooks with shell, ruby, python, and I could be wrong, but even PHP would work. pre-commit is a client-side hook (we have server side too) and he's located inside the .git/hooks folder. Let's jump to the code... Create a file called 'pre-commit' inside that folder with the following code.

+
#!/bin/bash
+npm test # assuming you're using it inside a nodeJS project
+
+

Don't forget to make the script executable!! Now break your test and try to commit. That's easy but can save you from breaking the tests at the main CI/Travis/Codeship/etc and being notified by email :). Why not even validate the lint of your project or check if the coverage doesn't fall? Does your team/company have a patter for commit messages? No problem, there is a hook called commit-msg that you can use to validate your message.

+

+
+ + +
+
+

Traduções:

+
    +
+
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/drafts/using_git_hooks_easy_your_life-en.html.gz b/pt/drafts/using_git_hooks_easy_your_life-en.html.gz new file mode 100644 index 000000000..7d8027a0b Binary files /dev/null and b/pt/drafts/using_git_hooks_easy_your_life-en.html.gz differ diff --git a/pt/editando-o-admin-do-django.html b/pt/editando-o-admin-do-django.html new file mode 100644 index 000000000..2cb905e28 --- /dev/null +++ b/pt/editando-o-admin-do-django.html @@ -0,0 +1,574 @@ + + + + + + + + Editando o Admin do Django - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Editando o Admin do Django

+
+ +
+
+ +
+

Este artigo foi re-postado no grupo PythonClub. Vamos falar um pouco sobre como customizar o admin do Django. Primeiramente porque? A resposta é bem simples, quero mostrar algo para o usuário sem que ele precise entrar nas apps e fazer alguma consulta para então tomar alguma ação. Alguns exêmplos para isto seriam:

+
+
    +
  • Exibir as vendas do mês em forma de gráfico por região do país
  • +
  • Exibir os últimos comentários adicionados
  • +
  • Exibir log dos ultimos usuários cadastrados
  • +
+
+

O que faremos aqui será exibir os últimos comentários ainda não liberados de um sistema de blog. Vale lembrar que aqui não discutiremos sobre os primeiros passos da aplicação. Para seguirmos adiante, vamos assumir que já temos um projeto básico com uma estrutura simples, abaixo a estrutura inicial do nosso projeto.

+
../blog/
+├── core
+│   ├── __init__.py
+│   ├── admin.py
+│   ├── models.py
+│   ├── tests.py
+│   └── views.py
+├── blog
+│   ├── __init__.py
+│   ├── settings.py
+│   ├── urls.py
+│   └── wsgi.py
+└── manage.py
+
+

Para iniciarmos, precisamos da nossa tabela de comentários, vamos usar a mais simples e básica o possível.

+ ++++ + + + + + + + + + + + + + + + + + + + +
CampoTipo
nomeVarchar(30)
textoText
liberadoBoolean
dataDate
+

Vamos seguir adiante e alterar a página inicial do admin para listar os últimos comentários de um simples sistema de blog. Para comerçar a editar o admin, precisamos inicialmente copiar o template que desejamos para a pasta uma pasta admin dentro ta pasta de templates do nosso projeto. Isto porque o Admin, não passa de uma app como outra qualquer, portanto o sistema de herança vai funcionar aqui, carregamento prioritariamente o seu template. Você pode conseguir o template que desejar (no nosso caso o index.html) dentro do projeto do Django mesmo, no meu caso "C:\Django-1.6.3\django\contrib\admin\templates\admin".

+
../blog/
+├── templates
+│   ├── admin
+│   │   └── index.html
+├── core
+
+

Tire um tempo e brinque um pouco com este template e veja o que acontece se você alterar algumas coisa. Para adicionarmos a nossa listagem, vamos adicionar um painel lateral, para tal vamos adicionar o código abaixo antes do fechamento da ultima tag div. Nele podemos ver uma chamada para uma template_tag, portanto precisamos carrega-la no topo do template.

+
{% load comentarios_tag %}
+...
+...
+...
+<div class="module" id="ultimos-comentarios">
+    <h2>Ultimos Comentários</h2>
+    <h3>Liberar</h3>
+            {% comentarios_n_liberados %}
+</div>
+
+

Esta template trata-se da responsável por fazer a consulta na base de dados e renderizar a nossa lista, portanto ela é uma 'inclusion tag'. Se você não esta familiarizado com 'template tags', talvez queira dar uma olhada na documentação do django.

+

Vamos então criar nossa template tag 'comentarios_n_liberados'. Primeiro devemos criar uma pasta chamada templatetags, dentro da nossa app core. Dentro ta pasta vamos inicializar um pacote python e criar o arquivo comentarios_tag.py. Nele precisamos declarar nosso metodo que deve se chamar 'comentarios_n_liberados' e nele fazer uma simples consulta ao banco buscando os comentários não liberados e por fim registrar a tag apontando para o template que será renderizado. Abaixo o código mais explicado.

+
+
Recomendações
+ Livro Pense em Python na Amazon + Livro Curso Intensivo de Python na Amazon +
from django import template
+from core import models
+
+#Carrega o registro de template tags
+register = template.Library()
+
+#Registra o metodo a seguir como uma inclusion_tag indicando o template a ser renderizad
+@register.inclusion_tag('comentarios_n_liberados.html')
+def comentarios_n_liberados():
+    comentarios = models.comentario.objects.filter(liberado=False).order_by('data')[0:5]
+    return { 'comentarios' : comentarios }
+
+

Abaixo o html do nosso template a ser renderizado, este deve estar dentro da pasta templates da nossa app core.

+
{% if not comentarios %}
+    <p>Nenhum comentário novo</p>
+{% else %}
+    <ul>
+            {% for c in comentarios %}
+            <li class="addlink">
+                    <a href="{{ c.id }}">{{ c.texto|truncatechars:30 }}</a>
+            </li>
+            {% endfor %}
+    </ul>
+{% endif %}
+
+

Com tudo isto feito, basta subir o seu servidor e ver o resultado final, que pode ser visto na imagem abaixo.

+Resultado final +

Lembrando que aqui apenas mostrei como modificar o index do admin, para apenas listar dados do banco, mas você pode ir muito mais além. Abaixo fica a estrutura de diretórios final e um link para download do projeto funcionando.

+
../blog/
+├── core
+│   ├── templates
+│   │   └── comentarios_n_liberados.html
+│   ├── templatetag
+│   │   └── comentarios_tag.py
+│   ├── __init__.py
+│   ├── admin.py
+│   ├── models.py
+│   ├── tests.py
+│   └── views.py
+├── blog
+│   ├── __init__.py
+│   ├── settings.py
+│   ├── urls.py
+│   └── wsgi.py
+├── templates
+│   ├── admin
+│   │   └── index.html
+└── manage.py
+
+

Espero que tenham gostado, criticas/sugestões são bem-vindas. Fontes do Projeto

+

+
+ + +
+
+

Traduções:

+
    +
+
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/editando-o-admin-do-django.html.gz b/pt/editando-o-admin-do-django.html.gz new file mode 100644 index 000000000..cd97b909e Binary files /dev/null and b/pt/editando-o-admin-do-django.html.gz differ diff --git a/pt/feeds/all-pt.atom.xml b/pt/feeds/all-pt.atom.xml new file mode 100644 index 000000000..30bcf5123 --- /dev/null +++ b/pt/feeds/all-pt.atom.xml @@ -0,0 +1,829 @@ + +Sipmannhttps://www.sipmann.com/pt/2020-12-21T13:30:00-03:00Monitorando restarts do MySQL com PowerShell2020-12-21T13:30:00-03:002020-12-21T13:30:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-12-21:/pt/monitoring-mysql-restarts-with-powershell.html<p>Bom, chegou a hora para mais um script PowerShell. Se você ainda não viu os outros, de uma olhada no link abaixo.</p> +<ul> +<li><a href="https://www.sipmann.com/pt/monitoring-mysql-replication-with-powershell.html">Monitorando status de replicação do MySQL com PowerShell</a></li> +</ul> +<p>Este aqui é um script bem simples, mas novamente, se seu cliente não possui um servidor Zabbix ou não permite …</p><p>Bom, chegou a hora para mais um script PowerShell. Se você ainda não viu os outros, de uma olhada no link abaixo.</p> +<ul> +<li><a href="https://www.sipmann.com/pt/monitoring-mysql-replication-with-powershell.html">Monitorando status de replicação do MySQL com PowerShell</a></li> +</ul> +<p>Este aqui é um script bem simples, mas novamente, se seu cliente não possui um servidor Zabbix ou não permite que você configure um para realizar este monitoramento, um conjunto de scripts pode ser bem útil. Primeiramente nós executamos uma query báscia <code>SHOW GLOBAL STATUS LIKE 'Uptime'</code>, com ela nós conseguimos capturar exatamente o que nós estamos procurando.</p> +<p>Se por alguma razão o comando falhar (verificamos atravez da variábel global <code>$lastExitCode</code>), nós mandamos um e-mail lhe avisando sobre o problema ocorrido.</p> +<p>E então, nós chegamos à parte onde fazemos o parse do valor obtido, esta parte é bem similar ao parse que codificamos no primeiro post sobre monitoramento utilizando PowerShell. Nós basicamentes procuramos pela linha contendo <code>Value</code>, separamos por espaço e então parseamos a segunda posição em um inteiro. Então tudo que precisamos fazer é verificar se o valor parseado é menor que o nosso threshold, se for menor, nós mandamos um e-mail.</p> +<div class="highlight"><pre><span></span><code><span class="nv">$MailFrom</span> <span class="p">=</span> <span class="s1">&#39;maurio[at]sipmann.com&#39;</span> +<span class="nv">$MailTo</span> <span class="p">=</span> <span class="s1">&#39;mauricio[at]sipmann.com&#39;</span> +<span class="nv">$MysqlHost</span> <span class="p">=</span> <span class="s1">&#39;127.0.0.1&#39;</span> +<span class="nv">$MysqlUser</span> <span class="p">=</span> <span class="s1">&#39;root&#39;</span> +<span class="nv">$MysqlPass</span> <span class="p">=</span> <span class="s1">&#39;123&#39;</span> + + +<span class="nv">$data</span> <span class="p">=</span> <span class="p">$(</span><span class="n">mysql</span> <span class="n">-h</span> <span class="nv">$MysqlHost</span> <span class="n">-u</span> <span class="nv">$MysqlUser</span> <span class="n">-p</span><span class="s2">&quot;$MysqlPass&quot;</span> <span class="n">-e</span> <span class="s2">&quot;SHOW GLOBAL STATUS LIKE &#39;Uptime&#39; \G&quot;</span><span class="p">)</span> + +<span class="cm">&lt;# Unable to execute the sql Command #&gt;</span> +<span class="k">if</span> <span class="p">(</span><span class="nv">$lastExitCode</span> <span class="o">-eq</span> <span class="n">1</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Send-MailMessage</span> <span class="n">-To</span> <span class="nv">$MailTo</span> <span class="n">-From</span> <span class="nv">$MailFrom</span> <span class="n">-Subject</span> <span class="s1">&#39;Connection problem&#39;</span> <span class="n">-bodyAsHtml</span> <span class="s2">&quot;Connection problem on host ${MysqlHost}&quot;</span> <span class="n">-Credential</span> <span class="nb">Get-Credential</span> <span class="n">-SmtpServer</span> <span class="s1">&#39;smtp.office365.com&#39;</span> <span class="n">-Port</span> <span class="n">587</span> <span class="n">-UseSsl</span> + <span class="n">exit</span> +<span class="p">}</span> + +<span class="nv">$UpTime</span> <span class="p">=</span> <span class="no">[int]</span><span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Value:&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> + +<span class="cm">&lt;# If the uptime is lower then 20 minutes #&gt;</span> +<span class="k">if</span> <span class="p">(</span><span class="nv">$UpTime</span> <span class="o">-lt</span> <span class="n">1200</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Send-MailMessage</span> <span class="n">-To</span> <span class="nv">$MailTo</span> <span class="n">-From</span> <span class="nv">$MailFrom</span> <span class="n">-Subject</span> <span class="s2">&quot;MySQL Restarted&quot;</span> <span class="n">-bodyAsHtml</span> <span class="s2">&quot;MySQL host ${MysqlHost} restarted less than 20 minutes ago&quot;</span> <span class="n">-Credential</span> <span class="nb">Get-Credential</span> <span class="n">-SmtpServer</span> <span class="s1">&#39;smtp.office365.com&#39;</span> <span class="n">-Port</span> <span class="n">587</span> <span class="n">-UseSsl</span> +<span class="p">}</span> +</code></pre></div> + +<p>Este script (e os outros que eu utilizo) estão disponíveis no meu GitHub <a href="https://github.com/sipmann/PowerShellScripts">aqui</a>. Tenha em mente que os scripts localizados no GitHub, são um pouco diferentes do que exibido aqui. Espero que tenha achado útil.</p>Trocando a senha de um usuário do MySQL sem downtime da aplicação2020-12-09T13:40:00-03:002020-12-09T13:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-12-09:/pt/mysql-dual-password-functionality.html<p>Você deseja trocar a senha de um usuário do MySQL que está sendo utilizado por uma aplicação e não sofrer nenhum downtime? Bom, a versão 8.0.14 do MySQL foi liberada com uma feature chamada <a href="https://dev.mysql.com/doc/refman/8.0/en/password-management.html#dual-passwords">Dual Password Support</a>, com esta feature você pode alterar a senha de um usuário …</p><p>Você deseja trocar a senha de um usuário do MySQL que está sendo utilizado por uma aplicação e não sofrer nenhum downtime? Bom, a versão 8.0.14 do MySQL foi liberada com uma feature chamada <a href="https://dev.mysql.com/doc/refman/8.0/en/password-management.html#dual-passwords">Dual Password Support</a>, com esta feature você pode alterar a senha de um usuário mantendo a anterior ainda funcionando como uma forma de "backup". Desta forma, você ainda conseguirá autenticar com o usuário utilizando tanto a nova senha, quanto a anterior. Com isto, o seu processo de troca de senha fica algo como:</p> +<p>1) Troque a senha mantendo a anterior;</p> +<p>2) Faça o Deploy da nova configuração na sua aplicação/cluster;</p> +<p>3) Descarte a senha anterior.</p> +<p>Para alterar a senha mantendo a anterior, você deve rodar o seguinte comando:</p> +<div class="highlight"><pre><span></span><code><span class="k">ALTER</span> <span class="n">USER</span> <span class="s1">&#39;appuser&#39;</span><span class="o">@</span><span class="s1">&#39;localhost&#39;</span> <span class="n">IDENTIFIED</span> <span class="k">BY</span> <span class="s1">&#39;new_password&#39;</span> <span class="n">RETAIN</span> <span class="n">CURRENT</span> <span class="n">PASSWORD</span><span class="p">;</span> +</code></pre></div> + +<p>Para descartar a senha antiga, rode o seguinte:</p> +<div class="highlight"><pre><span></span><code><span class="k">ALTER</span> <span class="n">USER</span> <span class="s1">&#39;appuser&#39;</span><span class="o">@</span><span class="s1">&#39;localhost&#39;</span> <span class="n">DISCARD</span> <span class="n">OLD</span> <span class="n">PASSWORD</span><span class="p">;</span> +</code></pre></div> + +<p>E pronto. Espero que isto lhe ajude a evitar downtimes e dores de cabeça :)</p>Apache Nifi JSON to SQL removendo underline2020-12-02T14:00:00-03:002020-12-02T14:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-12-02:/pt/apache-nifi-json-to-sql-replacing-underscore.html<p>Recentemente eu estava desenvolvendo alguns processos de ETL com o Apache NiFi. Mas após alguns minutos desenhando o meu fluxo, eu vi um comportamento estranho do componente ConvertJSONToSQL, que estava substituindo os underline ('_') do nome de um campo utilizado na condição da SQL (eu estava preparando um UPDATE). Aquilo …</p><p>Recentemente eu estava desenvolvendo alguns processos de ETL com o Apache NiFi. Mas após alguns minutos desenhando o meu fluxo, eu vi um comportamento estranho do componente ConvertJSONToSQL, que estava substituindo os underline ('_') do nome de um campo utilizado na condição da SQL (eu estava preparando um UPDATE). Aquilo estava estranho, uma vez que na definição do SET da SQL, o nome do campo permanecia inalterado. Depois de algumas pesquisas, achei uma doc que a propriedade (veja abaixo) <code>Translate Field Names</code> era a responsável por este comportamento estranho.</p> +<p><img alt="Apache NiFi JSONToSQL config" src="/images/apache_nifi_jsontosql.png"></p> +<p>Antes de definir a propriedade como <strong>FALSE</strong>, esteja ciente que as propriedades do seu JSON devem ser exatamente iguais aos nomes dos campos da sua tabela.</p>Bloqueando um usuário do SQL Server baseado em uma tabela de horários2020-11-14T07:00:00-03:002020-11-14T07:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-11-14:/pt/blocking-user-on-sql-server-based-on-schedule.html<p>Ok, algum tempo atrás, eu postei sobre como você pode impor limites às conexões do SQL Server utilizando o <a href="https://www.sipmann.com/limiting-connection-resources-sql-server.html#.X6Cz8IhKhPY">Resource Governor</a>. Mas, e se você não pode utilizar ele? Você sempre pode bloquear logins usando uma trigger, mas eu não gosto da ideia de ter um select rodando a cada …</p><p>Ok, algum tempo atrás, eu postei sobre como você pode impor limites às conexões do SQL Server utilizando o <a href="https://www.sipmann.com/limiting-connection-resources-sql-server.html#.X6Cz8IhKhPY">Resource Governor</a>. Mas, e se você não pode utilizar ele? Você sempre pode bloquear logins usando uma trigger, mas eu não gosto da ideia de ter um select rodando a cada login. Então, eu cheguei a esta solução, utilizando uma stored procedure, uma tabela e o Agent.</p> +<p>A ideia principal é armazenar o horário em que um usuário deve ser bloqueado pelo Agent. Abaixo você pode ver a criação da tabela:</p> +<div class="highlight"><pre><span></span><code><span class="k">CREATE</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"> </span><span class="p">(</span><span class="w"></span> +<span class="w"> </span><span class="n">Id</span><span class="w"> </span><span class="nc">INT</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">LoginName</span><span class="w"> </span><span class="nc">NVARCHAR</span><span class="p">(</span><span class="mi">100</span><span class="p">)</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">HrInicio</span><span class="w"> </span><span class="nc">TIME</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"> </span><span class="cm">/* horário de inicio do bloqueio */</span><span class="w"></span> +<span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="nc">TIME</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"> </span><span class="cm">/*horário de termino */</span><span class="w"></span> +<span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="nc">INT</span><span class="w"> </span><span class="k">DEFAULT</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="cm">/* 0 = desbloqueado, 1 = bloqueado */</span><span class="w"></span> +<span class="w"> </span><span class="k">PRIMARY</span><span class="w"> </span><span class="k">KEY</span><span class="w"> </span><span class="p">(</span><span class="n">Id</span><span class="p">)</span><span class="w"></span> +<span class="p">);</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> + +<span class="cm">/* regra para Não bloquear o usuário SA */</span><span class="w"></span> +<span class="k">ALTER</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"></span> +<span class="w"> </span><span class="k">ADD</span><span class="w"> </span><span class="k">CONSTRAINT</span><span class="w"> </span><span class="n">chk_users</span><span class="w"> </span><span class="k">CHECK</span><span class="w"> </span><span class="p">(</span><span class="n">LoginName</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;sa&#39;</span><span class="p">));</span><span class="w"></span> + +<span class="k">ALTER</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"></span> +<span class="w"> </span><span class="k">ADD</span><span class="w"> </span><span class="k">CONSTRAINT</span><span class="w"> </span><span class="n">chk_hora_final_maior</span><span class="w"> </span><span class="k">CHECK</span><span class="w"> </span><span class="p">(</span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="n">HrInicio</span><span class="p">);</span><span class="w"></span> + +<span class="k">ALTER</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"></span> +<span class="w"> </span><span class="k">ADD</span><span class="w"> </span><span class="k">CONSTRAINT</span><span class="w"> </span><span class="n">chk_status_bloqueio</span><span class="w"> </span><span class="k">CHECK</span><span class="w"> </span><span class="p">(</span><span class="n">Bloqueado</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">));</span><span class="w"></span> + +<span class="k">CREATE</span><span class="w"> </span><span class="k">SEQUENCE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">seq_HorariosBloqueio</span><span class="w"> </span><span class="k">START</span><span class="w"> </span><span class="k">WITH</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="n">INCREMENT</span><span class="w"> </span><span class="k">BY</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +</code></pre></div> + +<p>Depois de criar a tabela, vamos verificar a procedure que vai fazer todo o trabalho de habilitar/desabilitar os usuários. Fique ciente que, nesta procedure, eu defini o nome do banco onde a tabela está armazenada. Você pode substituir o nome <code>DBATOOLS</code> pelo o nome da sua base.</p> +<div class="highlight"><pre><span></span><code><span class="k">IF</span><span class="w"> </span><span class="nf">OBJECT_ID</span><span class="p">(</span><span class="s1">&#39;dbo.sp_ValidarLogin&#39;</span><span class="p">)</span><span class="w"> </span><span class="k">IS</span><span class="w"> </span><span class="k">NULL</span><span class="w"></span> +<span class="w"> </span><span class="k">EXEC</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;CREATE PROCEDURE dbo.sp_ValidarLogin AS RETURN 0;&#39;</span><span class="p">);</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> + +<span class="k">CREATE</span><span class="w"> </span><span class="ow">OR</span><span class="w"> </span><span class="k">ALTER</span><span class="w"> </span><span class="k">PROC</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">sp_ValidarLogin</span><span class="w"></span> +<span class="k">AS</span><span class="w"> </span><span class="k">BEGIN</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="nc">NVARCHAR</span><span class="p">(</span><span class="mi">100</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="nc">TIME</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="k">SET</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nf">CAST</span><span class="p">(</span><span class="nf">GETDATE</span><span class="p">()</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="nc">TIME</span><span class="p">);</span><span class="w"></span> + +<span class="w"> </span><span class="cm">/* Bloqueia os que ainda não estiverem bloqueados de acordo com a hora atual */</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="n">block_cursor</span><span class="w"> </span><span class="nc">CURSOR</span><span class="w"></span> +<span class="w"> </span><span class="k">FOR</span><span class="w"> </span><span class="k">SELECT</span><span class="w"> </span><span class="n">LoginName</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&lt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&gt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"></span> +<span class="w"> </span><span class="k">OPEN</span><span class="w"> </span><span class="n">block_cursor</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">block_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> + +<span class="w"> </span><span class="k">WHILE</span><span class="w"> </span><span class="nb">@@FETCH_STATUS</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"></span> +<span class="w"> </span><span class="k">BEGIN</span><span class="w"></span> +<span class="w"> </span><span class="k">exec</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;ALTER LOGIN &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="s1">&#39; DISABLE;&#39;</span><span class="p">);</span><span class="w"></span> + +<span class="w"> </span><span class="k">print</span><span class="w"> </span><span class="s1">&#39;Bloqued usuario &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">block_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> +<span class="w"> </span><span class="k">END</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">CLOSE</span><span class="w"> </span><span class="n">block_cursor</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="k">DEALLOCATE</span><span class="w"> </span><span class="n">block_cursor</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">UPDATE</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">SET</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&lt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&gt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"></span> + + +<span class="w"> </span><span class="cm">/* Libera quem estava bloqueado */</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="nc">CURSOR</span><span class="w"></span> +<span class="w"> </span><span class="k">FOR</span><span class="w"> </span><span class="k">SELECT</span><span class="w"> </span><span class="n">LoginName</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="p">(</span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">OR</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="p">)</span><span class="w"></span> +<span class="w"> </span><span class="k">OPEN</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> + +<span class="w"> </span><span class="k">WHILE</span><span class="w"> </span><span class="nb">@@FETCH_STATUS</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"></span> +<span class="w"> </span><span class="k">BEGIN</span><span class="w"></span> +<span class="w"> </span><span class="k">exec</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;ALTER LOGIN &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"> </span><span class="o">+</span><span class="s1">&#39; ENABLE;&#39;</span><span class="p">);</span><span class="w"></span> + +<span class="w"> </span><span class="k">print</span><span class="w"> </span><span class="s1">&#39;Unbloqued usuario &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> +<span class="w"> </span><span class="k">END</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">CLOSE</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="k">DEALLOCATE</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">UPDATE</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">SET</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="p">(</span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">OR</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="p">)</span><span class="w"></span> +<span class="k">END</span><span class="p">;</span><span class="w"></span> +</code></pre></div> + +<p>Certo, então agora tudo que temos que fazer é definir o job no Agent para rodar a procedure de minuto em minuto. Novamente, a ideia principal é chamar a procedure quando um usuário deve ser bloqueado e quando deve ser desbloqueado.</p> +<div class="highlight"><pre><span></span><code><span class="err"> -- Vai bloquear o usuário protheus das 10 AM até 15 PM</span> +<span class="err"> INSERT INTO dbo.HorariosBloqueio (Id, LoginName, HrInicio, HrTermino) VALUES (NEXT VALUE FOR seq_HorariosBloqueio, &#39;protheus&#39;, &#39;10:00:00&#39;, &#39;15:00:00&#39;);</span> +</code></pre></div>Como definir as colunas no select utilizando Entity Framework2020-10-28T19:00:00-03:002020-10-28T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-28:/pt/select_specific_fields_with_efcore.html<p>Então, você utiliza Entity Framework Core e geralmente faz o seu selecto da seguinte forma, talvez você está retornando muitos dados.</p> +<div class="highlight"><pre><span></span><code><span class="kt">var</span> <span class="n">products</span> <span class="p">=</span> <span class="n">Products</span> + <span class="p">.</span><span class="n">Where</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span> <span class="p">&gt;</span> <span class="m">0</span><span class="p">)</span> + <span class="p">.</span><span class="n">OrderBy</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">)</span> + <span class="p">.</span><span class="n">ToList</span><span class="p">()</span> +</code></pre></div> + +<p>Rodando a query acima, em uma base de testes você obtem o seguinte resultado, veja quantas …</p><p>Então, você utiliza Entity Framework Core e geralmente faz o seu selecto da seguinte forma, talvez você está retornando muitos dados.</p> +<div class="highlight"><pre><span></span><code><span class="kt">var</span> <span class="n">products</span> <span class="p">=</span> <span class="n">Products</span> + <span class="p">.</span><span class="n">Where</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span> <span class="p">&gt;</span> <span class="m">0</span><span class="p">)</span> + <span class="p">.</span><span class="n">OrderBy</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">)</span> + <span class="p">.</span><span class="n">ToList</span><span class="p">()</span> +</code></pre></div> + +<p>Rodando a query acima, em uma base de testes você obtem o seguinte resultado, veja quantas colunas estão retornando da sua base de dados.</p> +<p><img alt="Print com todas as colunas" src="/images/ef_core_allcolumns.png"></p> +<p>No meu caso, eu só pretendo ter de volta as colunas Title, PublishedData e uma pequena descrição. Então para selecionar apenas estes campos, nós temos algumas opções. Na primeira, nós vamos definir os campos e retornar um objeto do tipo Dynamic. A segunda forma, é dar ao .NET o objeto a ser retornado, pode ser por exêmplo um DTO.</p> +<div class="highlight"><pre><span></span><code><span class="kt">var</span> <span class="n">products</span> <span class="p">=</span> <span class="n">Products</span> + + <span class="p">.</span><span class="n">Select</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="k">new</span> <span class="p">{</span><span class="n">p</span><span class="p">.</span><span class="n">ProductID</span><span class="p">,</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">,</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span><span class="p">,</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitPrice</span><span class="p">})</span> + <span class="c1">//.Select(p =&gt; new ProductDTO {p.ProductID, p.ProductName, p.UnitsInStock, p.UnitPrice})</span> + + <span class="p">.</span><span class="n">Where</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span> <span class="p">&gt;</span> <span class="m">0</span><span class="p">)</span> + <span class="p">.</span><span class="n">OrderBy</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">)</span> + <span class="p">.</span><span class="n">ToList</span><span class="p">()</span> +</code></pre></div> + +<p><img alt="Print com menos colunas e também menor quantidade de dados" src="/images/ef_core_less_columns.png"></p>Zabbix Running on Low Memory Mode2020-10-20T19:00:00-03:002020-10-20T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-20:/pt/zabbix-running-on-low-memory-mode.html<p>Olá pessoal! Trago hoje outro post sobre Zabbix. Este é sobre aumentar o cache do seu Zabbix Server. É perfeitamente comum (se você roda com as configurações padrões) receber avisos sobre <code>Zabbix value cache running on low memory mode</code> no seu dashboard ou arquivos de log.</p> +<p><img alt="Zabbix Dashboard alertando sobre problemas de memória" src="/images/zabbix_low_memory_mode.png"> +<img alt="Zabbix Dashboard cache gráfico com 70% utilizado" src="/images/zabbix_cache_filling.png"></p> +<p>Para resolver, abra o …</p><p>Olá pessoal! Trago hoje outro post sobre Zabbix. Este é sobre aumentar o cache do seu Zabbix Server. É perfeitamente comum (se você roda com as configurações padrões) receber avisos sobre <code>Zabbix value cache running on low memory mode</code> no seu dashboard ou arquivos de log.</p> +<p><img alt="Zabbix Dashboard alertando sobre problemas de memória" src="/images/zabbix_low_memory_mode.png"> +<img alt="Zabbix Dashboard cache gráfico com 70% utilizado" src="/images/zabbix_cache_filling.png"></p> +<p>Para resolver, abra o seu arquivo de configuração (<code>zabbix_server.conf</code>) e procure pela tag <em>CacheSize</em>. Descomente a linha e defina um valor maior que 8M (8M é o valor padrão). No meu caso, nós configuramos um cache de 100M. Depois da troca, reinicie o serviço para que o mesmo tome efeito.</p> +<div class="highlight"><pre><span></span><code><span class="c1">### Option: CacheSize</span> +<span class="c1"># Size of configuration cache, in bytes.</span> +<span class="c1"># Shared memory size for storing host, item and trigger data.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 128K-64G</span> +<span class="c1"># Default:</span> +<span class="na">CacheSize</span><span class="o">=</span><span class="s">100M #Descomente esta linha</span> +</code></pre></div> + +<p><img alt="Zabbix Dashboard resolved memory problem" src="/images/zabbix_low_memory_solved.png"></p> +<p>Até breve.</p>Monitorando status de replicação do MySQL com PowerShell2020-10-14T19:00:00-03:002020-10-14T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-14:/pt/monitoring-mysql-replication-with-powershell.html<p>Tenho migrado alguns scripts bash que tenho para PowerShell, e chegou a vez de migrar um script de monitoramento de replicação do MySQL. Fica como crédito o script original do <a href="https://handyman.dulare.com/mysql-replication-status-alerts-with-bash-script/">Paweł</a>. É um script bem simples onde eu verifico algumas tags resultantes do <code>SHOW SLAVE STATUS\G</code>, são elas. <code>Slave_IO_Running …</code></p><p>Tenho migrado alguns scripts bash que tenho para PowerShell, e chegou a vez de migrar um script de monitoramento de replicação do MySQL. Fica como crédito o script original do <a href="https://handyman.dulare.com/mysql-replication-status-alerts-with-bash-script/">Paweł</a>. É um script bem simples onde eu verifico algumas tags resultantes do <code>SHOW SLAVE STATUS\G</code>, são elas. <code>Slave_IO_Running</code>, <code>Slave_SQL_Running</code> e <code>Seconds_Behind_Master</code>. Ainda preciso verificar formas mais corretas de armazenar/carregar as variáveis como usuários e senha, se tiver alguma dica, fique à vontade para inclusive fazer um pull request (<a href="https://github.com/sipmann/PowerShellScripts">aqui</a>) no repositório onde vou armazenar alguns dos meus scripts.</p> +<div class="highlight"><pre><span></span><code><span class="cm">&lt;#</span> +<span class="cm"> Variables definition</span> +<span class="cm">#&gt;</span> +<span class="nv">$MaxSeconds</span> <span class="p">=</span> <span class="n">120</span> <span class="c"># Max seconds behind master allowed</span> +<span class="nv">$MysqlUser</span> <span class="p">=</span> <span class="s1">&#39;root&#39;</span> +<span class="nv">$MysqlPass</span> <span class="p">=</span> <span class="s1">&#39;&#39;</span> + +<span class="nv">$MailTo</span> <span class="p">=</span> <span class="s1">&#39;mauricio@sipmann.com&#39;</span> +<span class="nv">$MailFrom</span> <span class="p">=</span> <span class="s1">&#39;mauricio@sipmann.com&#39;</span> + + +<span class="nv">$data</span> <span class="p">=</span> <span class="p">$(</span><span class="n">mysql</span> <span class="n">-u</span> <span class="nv">$MysqlUser</span> <span class="n">-p</span><span class="s2">&quot;$MysqlPass&quot;</span> <span class="n">-e</span> <span class="s1">&#39;SHOW SLAVE STATUS \G&#39;</span><span class="p">)</span> + +<span class="c">#Debug data</span> +<span class="c">#$data = Get-Content &#39;c:\temp\sampleresult.txt&#39;</span> + +<span class="cm">&lt;# Parse the data #&gt;</span> +<span class="nv">$IORunning</span> <span class="p">=</span> <span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Slave_IO_Running:&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> +<span class="nv">$SQLRunning</span> <span class="p">=</span> <span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Slave_SQL_Running:&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> +<span class="nv">$LastErrNo</span> <span class="p">=</span> <span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Last_Errno&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> +<span class="nv">$SecondsBh</span> <span class="p">=</span> <span class="no">[int]</span><span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Seconds_Behind_Master&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> + +<span class="k">If</span> <span class="p">(</span><span class="nv">$IORunning</span> <span class="o">-Eq</span> <span class="s1">&#39;No&#39;</span> <span class="o">-Or</span> <span class="nv">$SQLRunning</span> <span class="o">-Eq</span> <span class="s1">&#39;No&#39;</span> <span class="o">-Or</span> <span class="nv">$SecondsBh</span> <span class="o">-gt</span> <span class="nv">$MaxSeconds</span><span class="p">)</span> <span class="p">{</span> + <span class="nv">$MailBody</span> <span class="p">=</span> <span class="s1">&#39;&lt;h1&gt;Problema na replicação&lt;/h1&gt;&lt;br&gt;&#39;</span> + + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39; IO Running: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$IORunning</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39; SQL Running: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$SQLRunning</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39;Seconds Behind: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$SecondsBh</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39; Last Err No: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$LastErrNo</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + + <span class="cm">&lt;# Send e-mail, maybe some telegram message here too #&gt;</span> + <span class="nb">Send-MailMessage</span> <span class="n">-To</span> <span class="nv">$MailTo</span> <span class="n">-From</span> <span class="nv">$MailFrom</span> <span class="n">-Subject</span> <span class="s1">&#39;Problemas na replicação&#39;</span> <span class="n">-bodyAsHtml</span> <span class="nv">$MailBody</span> <span class="n">-Credential</span> <span class="p">(</span><span class="nb">Get-Credential</span><span class="p">)</span> <span class="n">-SmtpServer</span> <span class="s1">&#39;smtp.office365.com&#39;</span> <span class="n">-Port</span> <span class="n">587</span> <span class="n">-UseSsl</span> +<span class="p">}</span> <span class="k">Else</span> <span class="p">{</span> + <span class="nb">Write-Host</span> <span class="s2">&quot;Up and running&quot;</span> +<span class="p">}</span> +</code></pre></div>Microsoft Contra Covid2020-10-03T19:00:00-03:002020-10-03T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-03:/pt/microsoft-against-covid.html<p>Você teve seu trabalho afetado pela pandemia do covid? Bom, na última semana eu postei no <a href="https://grepora.com/2020/09/17/microsoft-ignite-certification-voucher/">Grepora</a> sobre um Voucher para certificação gratuita que a Microsoft estava distribuindo durante o evento Microsoft Ignite. Depois disto, eu fiquei sabendo que eles também estão entregando grandes discontos para quem teve o seu …</p><p>Você teve seu trabalho afetado pela pandemia do covid? Bom, na última semana eu postei no <a href="https://grepora.com/2020/09/17/microsoft-ignite-certification-voucher/">Grepora</a> sobre um Voucher para certificação gratuita que a Microsoft estava distribuindo durante o evento Microsoft Ignite. Depois disto, eu fiquei sabendo que eles também estão entregando grandes discontos para quem teve o seu trabalho afetado pela pandemia do covid. </p> +<p>Para saber se você pode receber este desconto, acesse <a href="https://docs.microsoft.com/en-us/learn/certifications/skillingoffer">https://docs.microsoft.com/en-us/learn/certifications/skillingoffer</a>.</p>O poder do PowerShell2020-09-21T19:00:00-03:002020-09-21T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-09-21:/pt/the-power-of-powershell.html<p>Como um usuário linux por muito tempo, eu automatizei algumas tarefas com scripts bash e fiquei longe do PowerShell... Voltei a utilizar Windows alguns anos atrás e ainda assim, não dei uma chance ao PS. Mas porque não? Eu fiz alguns scripts para automatizar algumas tarefas em um servidor Protheus …</p><p>Como um usuário linux por muito tempo, eu automatizei algumas tarefas com scripts bash e fiquei longe do PowerShell... Voltei a utilizar Windows alguns anos atrás e ainda assim, não dei uma chance ao PS. Mas porque não? Eu fiz alguns scripts para automatizar algumas tarefas em um servidor Protheus.</p> +<p>Eu acabei achando os scripts PS de fácil leitura e entendimento. Abaixo, nós temos um script para remover arquivos filtrando pela sua extensão (ou sem extensão alguma no caso do script em questão).</p> +<div class="highlight"><pre><span></span><code><span class="nb">Get-ChildItem</span> <span class="s2">&quot;C:\TOTVS\protheus_data\system&quot;</span> <span class="o">-File</span> <span class="n">-Filter</span> <span class="p">*.</span> <span class="p">|</span> <span class="nb">Move-Item</span> <span class="n">-Force</span> <span class="n">-Destination</span> <span class="p">{</span> + <span class="cm">&lt;# Diretório ao qual os arquivos vão ser movidos. Você pode utilizar formatos de data para nomear os diretórios #&gt;</span> + <span class="cm">&lt;# LastWriteTime é a propriedade do arquivo corrent #&gt;</span> + <span class="nv">$dir</span> <span class="p">=</span> <span class="s2">&quot;C:\bad_files\{0:yyyy\\MM\\dd}&quot;</span> <span class="o">-f</span> <span class="nv">$_</span><span class="p">.</span><span class="n">LastWriteTime</span> + <span class="nv">$null</span> <span class="p">=</span> <span class="n">mkdir</span> <span class="nv">$dir</span> <span class="n">-Force</span> + <span class="s2">&quot;$dir\</span><span class="p">$(</span><span class="nv">$_</span><span class="p">.</span><span class="n">Name</span><span class="p">)</span><span class="s2">&quot;</span> +<span class="p">}</span> +</code></pre></div> + +<p>Você já precisou remover arquivos baseado no conteúdo de outro arquivo? Abaixo um script onde eu leio um arquivo que contem os nomes de arquivos que eu desejo remover. </p> +<div class="highlight"><pre><span></span><code><span class="k">foreach</span><span class="p">(</span><span class="nv">$line</span> <span class="k">in</span> <span class="nb">Get-Content</span> <span class="p">.\</span><span class="n">Desktop</span><span class="p">\</span><span class="n">bad_files</span><span class="p">.</span><span class="n">txt</span><span class="p">)</span> <span class="p">{</span> + <span class="k">if</span> <span class="p">(</span><span class="nb">Test-Path</span><span class="p">(</span><span class="s1">&#39;\\x.y.z.a\c$\TOTVS\protheus_data\xmls\&#39;</span><span class="p">+</span><span class="nv">$line</span><span class="p">+</span><span class="s1">&#39;.xml&#39;</span><span class="p">))</span> <span class="p">{</span> + <span class="nb">Remove-Item</span><span class="p">(</span><span class="s1">&#39;\\x.y.z.a\c$\TOTVS\protheus_data\xmls\&#39;</span><span class="p">+</span><span class="nv">$line</span><span class="p">+</span><span class="s1">&#39;.xml&#39;</span><span class="p">)</span> + <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> + <span class="nb">echo </span><span class="nv">$line</span> <span class="p">+</span> <span class="s1">&#39; - File not found&#39;</span> + <span class="p">}</span> +<span class="p">}</span> +</code></pre></div> + +<p>E um script bonus para parar e iniciar serviços (se você gerencia um servidor Protheus, você sabe o porque eu faço isto).</p> +<div class="highlight"><pre><span></span><code><span class="nv">$servicesNames</span> <span class="p">=</span> <span class="s1">&#39;app_main&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker1&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker2&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker3&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker4&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker5&#39;</span> + +<span class="nb">Write-host</span> <span class="s2">&quot;Parando Serviços&quot;</span> +<span class="nb">Write-host</span> <span class="s2">&quot;--------------------------&quot;</span> + +<span class="k">foreach</span> <span class="p">(</span><span class="nv">$srv</span> <span class="k">in</span> <span class="nv">$servicesNames</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Write-host</span> <span class="s2">&quot;Parando: &quot;</span> <span class="p">+</span> <span class="nv">$srv</span> + <span class="nv">$SrvPID</span> <span class="p">=</span> <span class="p">(</span><span class="nb">get-wmiobject</span> <span class="n">win32_service</span> <span class="p">|</span> <span class="nb">where </span><span class="p">{</span> <span class="nv">$_</span><span class="p">.</span><span class="n">name</span> <span class="o">-eq</span> <span class="nv">$srv</span><span class="p">}).</span><span class="n">processID</span> + <span class="nb">Write-host</span> <span class="s2">&quot;PID: &quot;</span> <span class="p">+</span> <span class="nv">$SrvPID</span> + + <span class="cm">&lt;# Força a parada caso o serviço esteja travado #&gt;</span> + <span class="nb">Stop-Process</span> <span class="nv">$ServicePID</span> <span class="n">-Force</span> + <span class="nb">Write-host</span> <span class="s2">&quot;PDI &quot;</span> <span class="p">+</span> <span class="nv">$SrvPID</span> <span class="p">+</span> <span class="s2">&quot; parado&quot;</span> +<span class="p">}</span> + + +<span class="nb">Write-host</span> <span class="s2">&quot;Inicializando Serviços&quot;</span> +<span class="nb">Write-host</span> <span class="s2">&quot;--------------------------&quot;</span> + +<span class="k">foreach</span> <span class="p">(</span><span class="nv">$srv</span> <span class="k">in</span> <span class="nv">$servicesNames</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Write-host</span> <span class="s2">&quot;Inicializando: &quot;</span> <span class="p">+</span> <span class="nv">$srv</span> + <span class="nb">Start-Service</span> <span class="nv">$srv</span> +<span class="p">}</span> +</code></pre></div> + +<p>Você tem algum script de automação? Compartilhe conosco :)</p>Top Level Statement no C# 92020-07-29T19:00:00-03:002020-07-29T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-07-29:/pt/top_level_statement_csharp_9.html<p>Olá pessoal, venho hoje falar sobre uma novidade que estará disponível na versão 9 do C#. Toda vez que você deseja criar um novo projeto, você sempre tem o mesmo arquivo Main, com a mesma estrutura. Na próxima versão do C# (versão 9), nós teremos uma nova funcionalidade chamada <code>Top …</code></p><p>Olá pessoal, venho hoje falar sobre uma novidade que estará disponível na versão 9 do C#. Toda vez que você deseja criar um novo projeto, você sempre tem o mesmo arquivo Main, com a mesma estrutura. Na próxima versão do C# (versão 9), nós teremos uma nova funcionalidade chamada <code>Top Level Statement</code>. Com isto, poderemos programar a nossa aplicação sem toda aquela estrutura de <code>namespace/class/public void static main</code>. Veja o código abaixo.</p> +<div class="highlight"><pre><span></span><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span> + +<span class="n">Console</span><span class="p">.</span><span class="n">WriteLine</span><span class="p">(</span><span class="s">&quot;Hello World!&quot;</span><span class="p">);</span> +</code></pre></div> + +<p>Parece muito simples, não é? Com isto, você pode brincar com seu código e até mesmo programar uma pequena WEB API. Para começar a brincar com estas novas <em>features</em>, primeiramente faça o download do preview do <a href="https://dotnet.microsoft.com/download/dotnet/5.0">.net 5 SDK</a> e modifique o seu arquivo <code>.csproj</code> para apontar o framework para <code>.net5.0</code> e a versão de preview da linguagem. Abaixo como uma aplicação de console deve ficar.</p> +<div class="highlight"><pre><span></span><code><span class="nt">&lt;Project</span> <span class="na">Sdk=</span><span class="s">&quot;Microsoft.NET.Sdk&quot;</span><span class="nt">&gt;</span> + <span class="nt">&lt;PropertyGroup&gt;</span> + <span class="nt">&lt;OutputType&gt;</span>Exe<span class="nt">&lt;/OutputType&gt;</span> + <span class="nt">&lt;TargetFramework&gt;</span>net5.0<span class="nt">&lt;/TargetFramework&gt;</span> + <span class="nt">&lt;LangVersion&gt;</span>preview<span class="nt">&lt;/LangVersion&gt;</span> + <span class="nt">&lt;/PropertyGroup&gt;</span> +<span class="nt">&lt;/Project&gt;</span> +</code></pre></div> + +<p>E assim você está pronto para brincar com as novas funcionalidades que estão disponíveis na versão preview. Vamos programar uma aplicação simples que faz uma requisição na API da NASA e printe a Imagem do Dia no console. Não é nenhum código mirabolante, é simplesmente para exemplificar o quão simples uma simples chamada de API pode ser. Feito isto, porque não salvar a imagem como um arquivo? Ou então enviar essa imagem via telegram?</p> +<div class="highlight"><pre><span></span><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Net.Http</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Text.Json</span><span class="p">;</span> + +<span class="kt">var</span> <span class="n">API</span> <span class="p">=</span> <span class="s">&quot;https://api.nasa.gov/planetary/apod?hd=true&amp;api_key=DEMO_KEY&quot;</span><span class="p">;</span> +<span class="kt">var</span> <span class="n">cli</span> <span class="p">=</span> <span class="k">new</span> <span class="n">HttpClient</span><span class="p">();</span> + +<span class="kt">var</span> <span class="n">response</span> <span class="p">=</span> <span class="k">await</span> <span class="n">cli</span><span class="p">.</span><span class="n">GetAsync</span><span class="p">(</span><span class="n">API</span><span class="p">);</span> +<span class="kt">var</span> <span class="n">data</span> <span class="p">=</span> <span class="n">JsonSerializer</span><span class="p">.</span><span class="n">Deserialize</span><span class="p">&lt;</span><span class="n">NasaApi</span><span class="p">&gt;(</span><span class="k">await</span> <span class="n">response</span><span class="p">.</span><span class="n">Content</span><span class="p">.</span><span class="n">ReadAsStringAsync</span><span class="p">());</span> + +<span class="n">Console</span><span class="p">.</span><span class="n">WriteLine</span><span class="p">(</span><span class="n">data</span><span class="p">.</span><span class="n">Url</span><span class="p">);</span> +</code></pre></div> + +<p>Por hoje é isso. Fique de olho nas novas features que o C# 9 vai nos trazer. Já temos várias disponíveis hoje para testar, esta é apenas uma delas.</p>Zabbix poller processes more than 75%2020-07-02T19:00:00-03:002020-07-02T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-07-02:/pt/zabbix-poller-processes-more-than-75.html<p>Este é o terceiro post sobre configurações para o Zabbix. Todas as alterações que eu sugiro nestes posts, são baseadas em um servidor com 50+ hosts. Outro problema que pode ocorrer em seu servidor, é o poller de informações ficar sobrecarregado pela quantidade de servidores que ele precisa pegar carga …</p><p>Este é o terceiro post sobre configurações para o Zabbix. Todas as alterações que eu sugiro nestes posts, são baseadas em um servidor com 50+ hosts. Outro problema que pode ocorrer em seu servidor, é o poller de informações ficar sobrecarregado pela quantidade de servidores que ele precisa pegar carga de informações juntamente com os servidores que não respondem a requisição. Abaixo duas imagens onde você pode ver o log e um gráfico onde aparecem os percentuais de uso dos poller. </p> +<p><img alt="Dashboard log sobre o processo do poller" src="/images/zabbix_pooler.png"></p> +<p><img alt="Gráfico mostrando o percentual de utilização de cada coletor" src="/images/zabbix_pooler_3.png"></p> +<p>Para resolver o problema acima, vamos voltar ao arquivo de configuração <code>zabbix_server.conf</code> e localizar duas variáveis, <code>StartPollers</code> e <code>StartPollersUnreachable</code>. Aumente o valor delas conforme necessário. Não existe um número mágico, você deve verificar o que melhor funciona para você. Mas tenha em mente que <code>StartPollersUnreachable</code> é responsável por aqueles hosts que não respondem ou não são localizados e irão segurar a thread do poller por mais tempo, causando uma fila e um maior processamento/tempo de atualização.</p> +<div class="highlight"><pre><span></span><code><span class="c1">### Option: StartPollers</span> +<span class="c1"># Number of pre-forked instances of pollers.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 0-1000</span> +<span class="c1"># Default:</span> +<span class="na">StartPollers</span><span class="o">=</span><span class="s">20</span> + +<span class="c1">#...</span> + +<span class="c1">### Option: StartPollersUnreachable</span> +<span class="c1"># Number of pre-forked instances of pollers for unreachable hosts (including IPMI and Java).</span> +<span class="c1"># At least one poller for unreachable hosts must be running if regular, IPMI or Java pollers</span> +<span class="c1"># are started.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 0-1000</span> +<span class="c1"># Default:</span> +<span class="na">StartPollersUnreachable</span><span class="o">=</span><span class="s">5</span> +</code></pre></div> + +<p>Depois da alteração, reinicie o serviço e espere alguns momentos e veja o seu dashboard novamente. Abaixo o efeito que a troca teve em um dos servidores que acompanho.</p> +<p><img alt="Gráfico mostrando os novos percentuais de utilização dos processos após as alterações" src="/images/zabbix_pooler_4.png"></p>Monitorando a disponibilidade de um Website com Azure Functions2020-06-22T19:00:00-03:002020-06-22T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-06-22:/pt/monitoring-website-heath-with-azure-functions.html<p>Algumas vezes você se depara com a necessidade de monitorar a disponibilidade de um website ou mudanças em seu conteúdo. É claro que temos diversas opções disponíveis no mercado, mas para fins de curiosidade, vamos programar o nosso próprio e ver o que podemos fazer. Primeiramente, tudo que você ver …</p><p>Algumas vezes você se depara com a necessidade de monitorar a disponibilidade de um website ou mudanças em seu conteúdo. É claro que temos diversas opções disponíveis no mercado, mas para fins de curiosidade, vamos programar o nosso próprio e ver o que podemos fazer. Primeiramente, tudo que você ver aqui, você pode utilizar o <a href="https://azure.microsoft.com/free/">tier gratuito</a> da Azure.</p> +<p>A ideia principal da nossa aplicação vai ser monitorar a disponibilidade do website (status code). Para criar um projeto de Azure Function, siga os passos abaixo.</p> +<p><img alt="Passos para criar um projeto Azure Functions" src="/images/azure_functions.gif"></p> +<p>Depois de criar o projeto, você vai ter alguns arquivos. Abra o arquivo principal (<code>HttpCheck.cs</code> no meu caso) e começe a programar. O arquivo principal terá uma função chamada <code>Run</code> e você pode progamar nela o seu request. Eu criei um método <code>async</code> para fazer as requisições e printar a saída diretamente no console. O código completo pode ser visto abaixo.</p> +<div class="highlight"><pre><span></span><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Linq</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Net.Http</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Threading.Tasks</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">Microsoft.Azure.WebJobs</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">Microsoft.Azure.WebJobs.Host</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">Microsoft.Extensions.Logging</span><span class="p">;</span> + +<span class="k">namespace</span> <span class="nn">Sipmann.CheckMySite</span> +<span class="p">{</span> + <span class="k">public</span> <span class="k">static</span> <span class="k">class</span> <span class="nc">HttpCheck</span> + <span class="p">{</span> + + <span class="k">private</span> <span class="k">static</span> <span class="k">async</span> <span class="n">Task</span> <span class="nf">GetTask</span><span class="p">(</span><span class="kt">string</span> <span class="n">url</span><span class="p">,</span> <span class="n">ILogger</span> <span class="n">log</span><span class="p">)</span> + <span class="p">{</span> + <span class="kt">var</span> <span class="n">request</span> <span class="p">=</span> <span class="k">new</span> <span class="n">HttpRequestMessage</span><span class="p">(</span><span class="n">HttpMethod</span><span class="p">.</span><span class="n">Get</span><span class="p">,</span> <span class="n">url</span><span class="p">);</span> + + <span class="kt">var</span> <span class="n">client</span> <span class="p">=</span> <span class="k">new</span> <span class="n">HttpClient</span><span class="p">();</span> + <span class="kt">var</span> <span class="n">response</span> <span class="p">=</span> <span class="k">await</span> <span class="n">client</span><span class="p">.</span><span class="n">SendAsync</span><span class="p">(</span><span class="n">request</span><span class="p">);</span> + + <span class="k">if</span> <span class="p">(</span><span class="n">response</span><span class="p">.</span><span class="n">IsSuccessStatusCode</span><span class="p">)</span> + <span class="p">{</span> + <span class="n">log</span><span class="p">.</span><span class="n">LogInformation</span><span class="p">(</span><span class="err">$</span><span class="s">&quot;URL ${url} esta OK&quot;</span><span class="p">);</span> + <span class="p">}</span> + <span class="k">else</span> + <span class="p">{</span> + <span class="n">log</span><span class="p">.</span><span class="n">LogInformation</span><span class="p">(</span><span class="err">$</span><span class="s">&quot;URL ${url} não esta OK&quot;</span><span class="p">);</span> + <span class="p">}</span> + <span class="p">}</span> + +<span class="na"> [FunctionName(&quot;HttpCheck&quot;)]</span> + <span class="k">public</span> <span class="k">static</span> <span class="k">void</span> <span class="nf">Run</span><span class="p">([</span><span class="n">TimerTrigger</span><span class="p">(</span><span class="s">&quot;0 */5 * * * *&quot;</span><span class="p">)]</span><span class="n">TimerInfo</span> <span class="n">myTimer</span><span class="p">,</span> <span class="n">ILogger</span> <span class="n">log</span><span class="p">)</span> + <span class="p">{</span> + <span class="c1">// URL a verificar a saúde</span> + <span class="kt">var</span> <span class="n">urls</span> <span class="p">=</span> <span class="k">new</span><span class="p">[]{</span><span class="s">&quot;https://www.sipmann.com&quot;</span><span class="p">,</span> <span class="s">&quot;https://www.canezecanez.com.br&quot;</span><span class="p">};</span> + + <span class="c1">// Starta cada request e aguarda todos de uma vez só</span> + <span class="n">Task</span><span class="p">.</span><span class="n">WaitAll</span><span class="p">(</span><span class="n">urls</span><span class="p">.</span><span class="n">Select</span><span class="p">(</span><span class="n">url</span> <span class="p">=&gt;</span> <span class="n">GetTask</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">log</span><span class="p">)).</span><span class="n">ToArray</span><span class="p">());</span> + <span class="n">log</span><span class="p">.</span><span class="n">LogInformation</span><span class="p">(</span><span class="err">$</span><span class="s">&quot;Finalizou a fila&quot;</span><span class="p">);</span> + <span class="p">}</span> + <span class="p">}</span> +<span class="p">}</span> +</code></pre></div> + +<p>Agora você pode melhorar a função e talvez enviar alguns alertas. Como por exêmplo mensagens no Telegram quando um dos sites ficar off (status code 404).</p>Zabbix ICMP pinger processes more than 75%2020-05-25T16:00:00-03:002020-05-25T16:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-05-25:/pt/zabbix-icmp-pinger-processes-more-than-75.html<p>Então o seu systema de monitoramento creasceu e o seu Zabbix começou a printar "<em>Zabbix icmp pinger processes more than 75% busy</em>" no seu dashboard.</p> +<p><img alt="Dashboard do zabbix avisando sobre o erro" src="/images/zabbix_pinger01.png"></p> +<p>Tudo que você tem a fazer é abrir o seu arquivo de configuração (<code>/etc/zabbix/zabbix_server.conf</code>) e localizar a tag chamada <code>StartPingers</code>. Ela deve …</p><p>Então o seu systema de monitoramento creasceu e o seu Zabbix começou a printar "<em>Zabbix icmp pinger processes more than 75% busy</em>" no seu dashboard.</p> +<p><img alt="Dashboard do zabbix avisando sobre o erro" src="/images/zabbix_pinger01.png"></p> +<p>Tudo que você tem a fazer é abrir o seu arquivo de configuração (<code>/etc/zabbix/zabbix_server.conf</code>) e localizar a tag chamada <code>StartPingers</code>. Ela deve estar comentáda por padrão. Descomente a lina e define o seu valor para algo como 3 or 4. Deve resolver seu problema, ao menos até um próximo crescimento do seu monitoramento.</p> +<div class="highlight"><pre><span></span><code><span class="c1">### Option: StartPingers</span> +<span class="c1"># Number of pre-forked instances of ICMP pingers.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 0-1000</span> +<span class="c1"># Default:</span> +<span class="nv">StartPingers</span><span class="o">=</span><span class="m">4</span> +</code></pre></div>Zabbix Server Out of Memory2020-02-27T19:00:00-03:002020-02-27T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-02-27:/pt/zabbix-server-out-of-memory-crash.html<p>Você tem um servidor Zabbix crashando e observando o arquivo de log <code>/var/log/zabbix/zabbix_server.log</code> você localiza a seguinte mensagem referênciando falta de memória?</p> +<div class="highlight"><pre><span></span><code>__mem_malloc: skipped <span class="m">0</span> asked <span class="m">24</span> skip_min <span class="m">18446744073709551615</span> skip_max <span class="m">0</span> +<span class="o">[</span>file:dbconfig.c,line:94<span class="o">]</span> __zbx_mem_realloc<span class="o">()</span>: out of memory <span class="o">(</span>requested <span class="m">16</span> bytes<span class="o">)</span> +<span class="o">[</span>file:dbconfig.c …</code></pre></div><p>Você tem um servidor Zabbix crashando e observando o arquivo de log <code>/var/log/zabbix/zabbix_server.log</code> você localiza a seguinte mensagem referênciando falta de memória?</p> +<div class="highlight"><pre><span></span><code>__mem_malloc: skipped <span class="m">0</span> asked <span class="m">24</span> skip_min <span class="m">18446744073709551615</span> skip_max <span class="m">0</span> +<span class="o">[</span>file:dbconfig.c,line:94<span class="o">]</span> __zbx_mem_realloc<span class="o">()</span>: out of memory <span class="o">(</span>requested <span class="m">16</span> bytes<span class="o">)</span> +<span class="o">[</span>file:dbconfig.c,line:94<span class="o">]</span> __zbx_mem_realloc<span class="o">()</span>: please increase CacheSize configuration parameter +</code></pre></div> + +<p>Apesar da simples solução para o erro, isso acaba sendo um problema comum em servidores que tem uma certa quantidade de itens sendo monitorados (servidores, switches, firewalls, bancos, etc...). Para resolver o problema, vá até o ser arquivo <code>zabbix_server.conf</code> e procure pela propriedade <code>CacheSize</code> e sete o seu valor para uma quantidade maior. O seu valor default deve ser algo como 8M. Em clientes que tenham algo como 4 servidores, 7 firewalls/appliances, e algumas outras coisas (bancos, apps), 32M deve resolver o problema, mas você pode setar até algo como 8G (ressalto que mais memória nem sempre é melhor).</p> +<p>Até breve.</p>Removendo um usuário de uma base SQL Server2019-09-06T07:00:00-03:002020-10-21T18:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2019-09-06:/pt/removing-user-from-sql-server-database.html<p>O seu cliente lhe pede com urgência para <em>dropar</em> um usuário da sua base MsSQL Server, mas você trava com o seguinte aviso de erro:</p> +<div class="highlight"><pre><span></span><code><span class="n">Error</span><span class="o">:</span> <span class="mi">15138</span> <span class="n">The</span> <span class="n">database</span> <span class="n">principal</span> <span class="n">owns</span> <span class="n">a</span> <span class="n">schema</span> <span class="k">in</span> <span class="n">the</span> <span class="n">database</span><span class="o">,</span> <span class="n">and</span> <span class="n">cannot</span> <span class="n">be</span> <span class="n">dropped</span><span class="o">.</span> +</code></pre></div> + +<p>Se você não possui (ou no momento não consegue acesso …</p><p>O seu cliente lhe pede com urgência para <em>dropar</em> um usuário da sua base MsSQL Server, mas você trava com o seguinte aviso de erro:</p> +<div class="highlight"><pre><span></span><code><span class="n">Error</span><span class="o">:</span> <span class="mi">15138</span> <span class="n">The</span> <span class="n">database</span> <span class="n">principal</span> <span class="n">owns</span> <span class="n">a</span> <span class="n">schema</span> <span class="k">in</span> <span class="n">the</span> <span class="n">database</span><span class="o">,</span> <span class="n">and</span> <span class="n">cannot</span> <span class="n">be</span> <span class="n">dropped</span><span class="o">.</span> +</code></pre></div> + +<p>Se você não possui (ou no momento não consegue acesso) ao SSMS (SQL Server Management Studio) para verificar quais schemas ou objetos o usuário é "dono", a seguinte SQL vai resolver o problema.</p> +<div class="highlight"><pre><span></span><code><span class="k">USE</span><span class="w"> </span><span class="o">[</span><span class="n">DATABASENAME</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> + +<span class="k">select</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Objeto</span><span class="p">,</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Owner</span><span class="w"></span> +<span class="k">from</span><span class="w"> </span><span class="n">sys</span><span class="p">.</span><span class="n">schemas</span><span class="w"> </span><span class="n">so</span><span class="w"></span> +<span class="k">inner</span><span class="w"> </span><span class="k">join</span><span class="w"> </span><span class="n">sysusers</span><span class="w"> </span><span class="n">su</span><span class="w"> </span><span class="k">on</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">principal_id</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">uid</span><span class="w"></span> +<span class="k">where</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">&#39;username&#39;</span><span class="w"></span> + +<span class="k">select</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Objeto</span><span class="p">,</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Owner</span><span class="p">,</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">xtype</span><span class="w"> </span><span class="n">Tipo</span><span class="w"></span> +<span class="k">from</span><span class="w"> </span><span class="n">sys</span><span class="p">.</span><span class="n">sysobjects</span><span class="w"> </span><span class="n">so</span><span class="w"></span> +<span class="k">inner</span><span class="w"> </span><span class="k">join</span><span class="w"> </span><span class="n">sysusers</span><span class="w"> </span><span class="n">su</span><span class="w"> </span><span class="k">on</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">uid</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">uid</span><span class="w"></span> +<span class="k">where</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">&#39;username&#39;</span><span class="w"></span> +</code></pre></div> + +<p>Assim que você tiver os objetos/schemas que o usuário é dono, você pode alterar os mesmos com a seguinte SQL (exemplo de troca de schema):</p> +<div class="highlight"><pre><span></span><code><span class="k">USE</span><span class="w"> </span><span class="o">[</span><span class="n">DATABASENAME</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +<span class="k">ALTER</span><span class="w"> </span><span class="k">AUTHORIZATION</span><span class="w"> </span><span class="k">ON</span><span class="w"> </span><span class="k">SCHEMA</span><span class="o">::[</span><span class="n">db_datareader</span><span class="o">]</span><span class="w"> </span><span class="k">TO</span><span class="w"> </span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="w"> </span><span class="c1">-- username do novo dono</span> +<span class="k">ALTER</span><span class="w"> </span><span class="k">AUTHORIZATION</span><span class="w"> </span><span class="k">ON</span><span class="w"> </span><span class="k">SCHEMA</span><span class="o">::[</span><span class="n">db_datawriter</span><span class="o">]</span><span class="w"> </span><span class="k">TO</span><span class="w"> </span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +</code></pre></div> + +<p>Então, você pode dropar o usuário <code>DROP USER [username]</code>.</p>Resolvendo java.net.SocketException: Protocol family unavailable em Java + Docker + WildFly2018-03-04T17:40:00-03:002018-03-04T17:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-03-04:/pt/socketException-protocol-family-unavailable-java-docker-wildfly.html<p>Nos últimos dias eu estou brincando com o <a class="reference external" href="http://wildfly-swarm.io/">WildFly Swarm</a> e decidi fazer o deploy de uma aplicação simples com Docker. Deveria funcionar bem, ao menos é o que pensava. Construí um container com o seguinte Dockerfile e ao invés de obter uma aplicação web, tudo que eu obtive foi …</p><p>Nos últimos dias eu estou brincando com o <a class="reference external" href="http://wildfly-swarm.io/">WildFly Swarm</a> e decidi fazer o deploy de uma aplicação simples com Docker. Deveria funcionar bem, ao menos é o que pensava. Construí um container com o seguinte Dockerfile e ao invés de obter uma aplicação web, tudo que eu obtive foi o erro <cite>java.net.SocketException: Protocol family unavailable</cite>.</p> +<div class="highlight"><pre><span></span><span class="k">FROM</span> <span class="s">java:openjdk-8-jdk</span> + +<span class="k">COPY</span> target/issues.jar /opt/issues.jar + +<span class="k">EXPOSE</span><span class="s"> 8080</span> + +<span class="k">CMD</span> <span class="p">[</span><span class="s2">&quot;java&quot;</span><span class="p">,</span><span class="s2">&quot;-jar&quot;</span><span class="p">,</span><span class="s2">&quot;/opt/issues.jar&quot;</span><span class="p">]</span> +</pre></div> +<p>Por alguma razão, WildFly e Java, ambos decidiram utilizar um protocolo IPv6 na interface de rede no Docker invés da v4, então tudo que você tem que fazer é falar ao Java que deve dar preferência em utilizar o IPv4 com a seguinte configuração no seu arquivo pom.xml dentro da tag do plugin WildFly.</p> +<div class="highlight"><pre><span></span><span class="nt">&lt;plugin&gt;</span> + <span class="nt">&lt;groupId&gt;</span>org.wildfly.swarm<span class="nt">&lt;/groupId&gt;</span> + <span class="nt">&lt;artifactId&gt;</span>wildfly-swarm-plugin<span class="nt">&lt;/artifactId&gt;</span> + <span class="nt">&lt;version&gt;</span>2018.2.0<span class="nt">&lt;/version&gt;</span> + + <span class="c">&lt;!-- ADICIONE ISTO --&gt;</span> + <span class="nt">&lt;configuration&gt;</span> + <span class="nt">&lt;mainClass&gt;</span>org.wildfly.swarm.examples.netflix.ribbon.frontend.Main<span class="nt">&lt;/mainClass&gt;</span> + <span class="nt">&lt;properties&gt;</span> + <span class="nt">&lt;java.net.preferIPv4Stack&gt;</span>true<span class="nt">&lt;/java.net.preferIPv4Stack&gt;</span> + <span class="nt">&lt;/properties&gt;</span> + <span class="nt">&lt;/configuration&gt;</span> +</pre></div> +<p>Outra forma de solucionar o problema, é adicionando a mesma propriedade ao comando de run no seu Dockerfile. Então, fica a seu critério onde adicionar. Abaixo a solução utilizando o Dockerfile.</p> +<div class="highlight"><pre><span></span><span class="k">FROM</span> <span class="s">java:openjdk-8-jdk</span> +<span class="k">ENV</span> <span class="nv">JAVA_OPTS</span><span class="o">=</span><span class="s2">&quot;-Djava.net.preferIPv4Stack=true -Djava.net.preferIPv4Addresses=true&quot;</span> + +<span class="k">COPY</span> target/issues.jar /opt/issues.jar + +<span class="k">EXPOSE</span><span class="s"> 8080</span> + +<span class="k">ENTRYPOINT</span> <span class="nb">exec</span> java <span class="nv">$JAVA_OPTS</span> -jar /opt/issues.jar +</pre></div> +Menu dinâmico com as apps do django2018-01-21T21:17:00-02:002018-01-21T21:17:00-02:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-01-21:/pt/menu-dinamico-com-apps-do-django.html<p>Digamos que sua empresa trabalha com Django desenvolvendo aplicações cujas apps são plugaveis e reutilizáveis. Por que não se aproveitar de um certo padrão de desenvolvimento para desenvolver menus que se modificam de acordo com as apps que estão no projeto? Como o objetivo aqui não é desenvolver uma app …</p><p>Digamos que sua empresa trabalha com Django desenvolvendo aplicações cujas apps são plugaveis e reutilizáveis. Por que não se aproveitar de um certo padrão de desenvolvimento para desenvolver menus que se modificam de acordo com as apps que estão no projeto? Como o objetivo aqui não é desenvolver uma app em si, vamos utilizar um projeto com algumas de modelo. Se desejar estudar mais sobre desenvolvimento Django, a documentação é muito boa, mas também temos blogs e sites excelentes sobre o assunto.</p> +<p>Para conseguirmos atingir esse objetivo, vamos utilizar a api <a class="reference external" href="https://docs.djangoproject.com/en/2.0/ref/settings/#installed-apps">Django.apps</a> que está disponível a partir da versão 1.7. +Com esta api, vamos percorrer as apps e se possível, criar um link para uma URL base de cada uma delas. Para começo, baixe os fontes do <a class="reference external" href="https://github.com/sipmann/menusapp-django/releases/tag/v1">projeto aqui</a>, rode o pip install do projeto e no fim, sua estrutura de pastas deve ficar como abaixo.</p> +<div class="highlight"><pre><span></span>../menusapp/ +├── comentarios +│ ├── templates +│ │ └── comentarios +│ │ └── listagem.html +│ ├── __init__.py +│ ├── admin.py +│ ├── apps.py +│ ├── models.py +│ ├── tests.py +│ ├── urls.py +│ └── views.py +├── core +│ ├── templates +│ │ └── core +│ │ └── base.html +│ │ └── listagem.html +│ ├── __init__.py +│ ├── admin.py +│ ├── apps.py +│ ├── models.py +│ ├── tests.py +│ ├── urls.py +│ └── views.py +├── menusapp +│ ├── __init__.py +│ ├── settings.py +│ ├── urls.py +│ └── wsgi.py +└── manage.py +</pre></div> +<p>Rode o projeto e veja como é o seu funcionamento. É na app core que temos a base do nosso HTML, então será nele que iremos trabalhar. Quando se trata de algo que será renderizado no template base, eu gosto muito de utilizar 'template tags' para facilitar. +Neste <a class="reference external" href="http://www.sipmann.com/editando-o-admin-do-django.html">link</a> tem mais um exemplo de utilização de 'template tag' caso esteja interessado.</p> +<p>Vamos então criar uma pasta chamada template_tag e dentro dela a nossa tag. Vamos chamá-la de menus_tag.py. Abaixo vamos ver um pouco da nossa tag. +O código é bem simples e auto explicativo, importamos as bibliotecas necessárias e realizamos o &#64;register da tag com o nome do template que será renderizado. +E por ultimo, retornamos uma tupla de dados para o template.</p> +<div class="livros"> + <div class="recomendacoes">Recomendações</div> + <a rel="noopener" href="https://www.amazon.com.br/gp/product/8575225081/ref=as_li_ss_il?ie=UTF8&linkCode=li2&tag=sipmann-20&linkId=c17fa3ac84e734741a3761e874d7d286" target="_blank"><img border="0" src="//ws-na.amazon-adsystem.com/widgets/q?_encoding=UTF8&ASIN=8575225081&Format=_SL160_&ID=AsinImage&MarketPlace=BR&ServiceVersion=20070822&WS=1&tag=sipmann-20" ></a><img src="https://ir-br.amazon-adsystem.com/e/ir?t=sipmann-20&l=li2&o=33&a=8575225081" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /> + <a rel="noopener" href="https://www.amazon.com.br/gp/product/B074ZTLKHB/ref=as_li_ss_il?ie=UTF8&linkCode=li2&tag=sipmann-20&linkId=e2f37c07da2dc4111ae47854b205d01a" target="_blank"><img border="0" src="//ws-na.amazon-adsystem.com/widgets/q?_encoding=UTF8&ASIN=B074ZTLKHB&Format=_SL160_&ID=AsinImage&MarketPlace=BR&ServiceVersion=20070822&WS=1&tag=sipmann-20" ></a><img src="https://ir-br.amazon-adsystem.com/e/ir?t=sipmann-20&l=li2&o=33&a=B074ZTLKHB" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /> +</div><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django</span> <span class="kn">import</span> <span class="n">template</span> +<span class="kn">from</span> <span class="nn">django.apps</span> <span class="kn">import</span> <span class="n">apps</span> + +<span class="c1">#Carrega o registro de template tags</span> +<span class="n">register</span> <span class="o">=</span> <span class="n">template</span><span class="o">.</span><span class="n">Library</span><span class="p">()</span> + +<span class="c1">#Registra o metodo a seguir como uma inclusion_tag indicando o template a ser renderizado</span> +<span class="nd">@register</span><span class="o">.</span><span class="n">inclusion_tag</span><span class="p">(</span><span class="s1">&#39;menus_por_app.html&#39;</span><span class="p">)</span> +<span class="k">def</span> <span class="nf">menus_por_app</span><span class="p">():</span> + <span class="n">lst</span> <span class="o">=</span> <span class="n">apps</span><span class="o">.</span><span class="n">get_app_configs</span><span class="p">()</span> + <span class="k">return</span> <span class="p">{</span> <span class="s1">&#39;lst_apps&#39;</span> <span class="p">:</span> <span class="n">lst</span> <span class="p">}</span> +</pre></div> +<p>O template está abaixo e é simplesmente um for percorrendo as apps e gerando uma lista com os seus menus. As outras propriedades você pode ver direto na <a class="reference external" href="https://docs.djangoproject.com/en/2.0/ref/applications/#django.apps.AppConfig">documentação</a>. +Algumas ressalvas para o que foi feito por questões de praticidade para uso posterior, utilizei um with para concatenar e gerar a url e criei um apelido para a url para validar a existência da mesma. Fora isto, nada de novo.</p> +<div class="highlight"><pre><span></span>{% if not lst_apps %} + <span class="p">&lt;</span><span class="nt">p</span><span class="p">&gt;</span>Nenhuma app<span class="p">&lt;/</span><span class="nt">p</span><span class="p">&gt;</span> + {% else %} + <span class="p">&lt;</span><span class="nt">ul</span><span class="p">&gt;</span> + {% for app in lst_apps %} + {% with app.name|add:&quot;:listagem&quot; as link %} + {% url link as the_url %} + {% if the_url %} + <span class="p">&lt;</span><span class="nt">li</span><span class="p">&gt;</span> + <span class="p">&lt;</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">&quot;{% url link %}&quot;</span><span class="p">&gt;</span>{{ app.verbose_name|truncatechars:30 }}<span class="p">&lt;/</span><span class="nt">a</span><span class="p">&gt;</span> + <span class="p">&lt;/</span><span class="nt">li</span><span class="p">&gt;</span> + {% endif %} + {% endwith %} + {% endfor %} + <span class="p">&lt;/</span><span class="nt">ul</span><span class="p">&gt;</span> + {% endif %} +</pre></div> +<img alt="Resultado final" src="/images/menu_apps.png" /> +<p>No final, o resultado obtido deve ser semelhante ao acima. Repare que está listando as duas aplicações. E acima de tudo, repare que só serão exibidos os links cuja app tenha um namespace de mesmo nome e uma url de nome <cite>listagem</cite>. +A estrutura final pode ser vista abaixo. Atente-se aos nomes tanto das pastas quanto dos arquivos, pois qualquer diferença pode causar o não funcionamento.</p> +<div class="highlight"><pre><span></span>../menusapp/ +├── comentarios +│ ├── templates +│ │ └── comentarios +│ │ └── listagem.html +│ ├── __init__.py +│ ├── admin.py +│ ├── apps.py +│ ├── models.py +│ ├── tests.py +│ ├── urls.py +│ └── views.py +├── core +│ ├── templates +│ │ └── core +│ │ │ └── base.html +│ │ │ └── listagem.html +│ │ └── menus_por_app.html +│ ├── templatetags +│ │ ├── __init__.py +│ │ └── menus_tag.py +│ ├── __init__.py +│ ├── admin.py +│ ├── apps.py +│ ├── models.py +│ ├── tests.py +│ ├── urls.py +│ └── views.py +├── menusapp +│ ├── __init__.py +│ ├── settings.py +│ ├── urls.py +│ └── wsgi.py +└── manage.py +</pre></div> +<p>Espero que tenham gostado, críticas e sugestões são bem-vindas. <a class="reference external" href="https://github.com/sipmann/menusapp-django/releases/tag/v2">Fontes do Projeto</a></p> +Scripts de inicialização no raspberry pi2017-10-08T18:00:00-03:002017-10-08T18:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2017-10-08:/pt/script-de-inicializacao-raspberry.html<p>Instalei essa semana o <a class="reference external" href="https://gitea.io">gitea</a> no meu raspberry pi B + e queria iniciar ele no boot... Não sou profundo conhecedor de linux, então, logo não sabia como fazer isto da melhor forma. +As versões atuais do Raspbian utilizam o <cite>systemd</cite> para gerenciar os serviços e confesso que nunca havia utilizado …</p><p>Instalei essa semana o <a class="reference external" href="https://gitea.io">gitea</a> no meu raspberry pi B + e queria iniciar ele no boot... Não sou profundo conhecedor de linux, então, logo não sabia como fazer isto da melhor forma. +As versões atuais do Raspbian utilizam o <cite>systemd</cite> para gerenciar os serviços e confesso que nunca havia utilizado o systemctl para nada.</p> +<p>Vamos começa criando um arquivo de serviço dentro da pasta <cite>/etc/systemd/system</cite>, vale ressaltar que a pasta <cite>system</cite> deve (em teoria) ser reservada para pacotes do sistema. +Vamos criar o arquivo com o nome <cite>gitea.service</cite> dentro da pasta antes mencionada. Abaixo podemos ver como ficou o arquivo e um detalhamento após ele.</p> +<div class="highlight"><pre><span></span><span class="o">[</span>Unit<span class="o">]</span> +<span class="nv">Description</span><span class="o">=</span>Gitea Service +<span class="nv">After</span><span class="o">=</span>network.target + +<span class="o">[</span>Service<span class="o">]</span> +<span class="nv">Type</span><span class="o">=</span>simple +<span class="nv">User</span><span class="o">=</span>root +<span class="nv">WorkingDirectory</span><span class="o">=</span>/root/ +<span class="nv">ExecStart</span><span class="o">=</span>/root/gitea web +<span class="nv">Restart</span><span class="o">=</span>on-abort +</pre></div> +<p>A composição do arquivo é bem simples, mas vamos a alguns detalhes. <cite>Type</cite> possui várias opções (simple, forking, oneshot), utilizamos <cite>simple</cite> uma vez que o nosso processo executara, permanecerá rodando e não executa um fork de processo. +Fork como acabo de comentar, deve ser utilizado caso o processo que for executando disparar mais processos. User irá definir o usuário do processo. <cite>WorkingDirectory</cite> definira onde o processo terá a sua base de execução, como o gitea esta localizada na pasta root, +aponto para lá. O ExecStart é bem simples e direto, deve chamar a execução do processo passando parametros caso seja necessário. O <cite>Restart</cite> é o que nos garantirá que o serviço permanecerá rodando caso haja algum imprevisto (exceto o fato de um usuário chamar o stop).</p> +<p>Salve o arquivo e vamos rodar um refresh para o SO perceber o novo serviço. Assim rodamos <cite>systemctl daemon-reload</cite>. Sempre que alterarmos um serviço ou criarmos um novo, este comando deve ser executado, caso contrário o próprio systemctl pode lhe alertar da necessidade. +Após reacarregar os serviços, vamos habilitar o serviço que criamos rodando <cite>systemctl enable gitea</cite>, feito isto temos alguns comandos uteis.</p> +<ul class="simple"> +<li>systemctl start gitea</li> +<li>systemctl stop gitea</li> +<li>systemctl status gitea</li> +</ul> +<p>O comando de status pode ser visto como exemplo abaixo.</p> +<div class="highlight"><pre><span></span>● gitea.service - Gitea Service + Loaded: loaded <span class="o">(</span>/etc/systemd/system/gitea.service<span class="p">;</span> enabled<span class="p">;</span> vendor preset: enabled<span class="o">)</span> + Active: active <span class="o">(</span>running<span class="o">)</span> since Wed <span class="m">2017</span>-10-04 <span class="m">00</span>:37:34 UTC<span class="p">;</span> 52min ago +Main PID: <span class="m">1087</span> <span class="o">(</span>gitea<span class="o">)</span> + CGroup: /system.slice/gitea.service + └─1087 /root/gitea web + +Oct <span class="m">04</span> <span class="m">00</span>:38:31 gitserver gitea<span class="o">[</span><span class="m">1087</span><span class="o">]</span>: <span class="o">[</span>Macaron<span class="o">]</span> <span class="m">2017</span>-10-04 <span class="m">00</span>:38:31: Completed /explore/users <span class="m">200</span> OK in <span class="m">80</span>.106173ms +Oct <span class="m">04</span> <span class="m">00</span>:38:31 gitserver gitea<span class="o">[</span><span class="m">1087</span><span class="o">]</span>: <span class="o">[</span>Macaron<span class="o">]</span> <span class="m">2017</span>-10-04 <span class="m">00</span>:38:31: Started GET /img/favicon.png <span class="k">for</span> <span class="m">192</span>.168.1.4 +Oct <span class="m">04</span> <span class="m">00</span>:38:31 gitserver gitea<span class="o">[</span><span class="m">1087</span><span class="o">]</span>: <span class="o">[</span>Macaron<span class="o">]</span> <span class="o">[</span>Static<span class="o">]</span> Serving /img/favicon.png +</pre></div> +<p>Após estes processos, você pode reiniciar seu raspberry que o gitea irá subir e funcionar. Ressalto que, preste atenção tanto no <cite>WorkingDirectory</cite> quanto no <cite>ExecStart</cite>, no caso do gitea, ele utiliza o workingdir e a forma de start para saber onde irá largar os arquivos por padrão, então ou você configura ele com caminhos absolutos ou cuidar na forma de start (ao menos é o que consegui pegar até agora).</p> +Cool Tools2017-09-17T14:00:00-03:002017-09-17T14:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2017-09-17:/pt/cool-tools.html<p>Com o passar do tempo você vai &quot;encontrando&quot; - e às vezes até mesmo desenvolvendo - algumas ferramentas que tornam o seu dia a dia como desenvolvedor mais fácil. Abaixo seguem algumas das minhas ferramentas que costumo usar. Ressalto que essa lista será (provavelmente) atualizada com o passar do tempo.</p> +<div class="section" id="https-www-gitkraken-com"> +<h2><a class="reference external" href="https://www.gitkraken.com">https://www …</a></h2></div><p>Com o passar do tempo você vai &quot;encontrando&quot; - e às vezes até mesmo desenvolvendo - algumas ferramentas que tornam o seu dia a dia como desenvolvedor mais fácil. Abaixo seguem algumas das minhas ferramentas que costumo usar. Ressalto que essa lista será (provavelmente) atualizada com o passar do tempo.</p> +<div class="section" id="https-www-gitkraken-com"> +<h2><a class="reference external" href="https://www.gitkraken.com">https://www.gitkraken.com</a></h2> +<p>Eu gosto muito de usar git, mas às vezes fico cansado de ter que usar só linha de comando, e achei no GitKreaken uma interface muito legal de se usar.</p> +</div> +<div class="section" id="http-paletton-com"> +<h2><a class="reference external" href="http://paletton.com">http://paletton.com</a></h2> +<p>Toda vez que você vai fazer um novo sistema/site, ou até mesmo trocar o layout de algum já existente, você acaba tendo que montar uma paleta de cores para se utilizar em todo o template.</p> +</div> +<div class="section" id="https-icomoon-io-app-select"> +<h2><a class="reference external" href="https://icomoon.io/app/#/select">https://icomoon.io/app/#/select</a></h2> +<p>Querendo usar ícones como fontes? Vá aí e gere apenas os arquivos que você vai realmente utilizar e economize alguns kbs.</p> +</div> +<div class="section" id="https-syncthing-net"> +<h2><a class="reference external" href="https://syncthing.net/">https://syncthing.net/</a></h2> +<p>Se você procura algum meio de sincronizar seus arquivos entre vários pcs e por algum motivo não quer usar um Google Drive ou DropBox, fica aqui a indicação deste cara.</p> +</div> +<div class="section" id="http-sqitch-org"> +<h2><a class="reference external" href="http://sqitch.org/">http://sqitch.org/</a></h2> +<p>Gerenciamento de versões de um banco de dados pode ser bem complicado e trabalhoso... Manter diversos ambientes (desenvolvimento, homologação, produção) vai dar um trabalho se não utilizar alguma ferramenta. Porque não usar o melhor de gerenciamento de versão (git) e uma ferramenta que se adequa ao que você precisa? sqitch é o cara nessas horas.</p> +</div> +<div class="section" id="http-www-setupmyproject-com"> +<h2><a class="reference external" href="http://www.setupmyproject.com/">http://www.setupmyproject.com/</a></h2> +<p>Preparação de projetos java, com frameworks, bibliotecas, nomenclatura, etc... Rende uma economia de tempo grandiosa e já vem tudo pronto :).</p> +</div> +<div class="section" id="https-www-pexels-com"> +<h2><a class="reference external" href="https://www.pexels.com/">https://www.pexels.com/</a></h2> +<p>Bom site para imagens free stock. Excelente local para conseguir imagens de alta qualidade.</p> +</div> +<div class="section" id="https-heml-io"> +<h2><a class="reference external" href="https://heml.io/">https://heml.io/</a></h2> +<p>&quot;HEML is an open source markup language for building responsive email.&quot; Melhor descrição impossível.</p> +</div> +<div class="section" id="https-www-mockapi-io"> +<h2><a class="reference external" href="https://www.mockapi.io/">https://www.mockapi.io/</a></h2> +<p>Desenvolva mocks para testar seu front-end. Eles geram inclusive uma carga de dados para ser utilizado nos seus testes.</p> +</div> +<div class="section" id="https-undraw-co"> +<h2><a class="reference external" href="https://undraw.co">https://undraw.co</a></h2> +<p>Needing some cool and free ilustrations? Take a look at it.</p> +</div> +<div class="section" id="https-www-audiotool-com-app"> +<h2><a class="reference external" href="https://www.audiotool.com/app/">https://www.audiotool.com/app/</a></h2> +<p>Ferramenta para criar sons, musicas e afins</p> +</div> +<div class="section" id="https-app-cloudskew-com"> +<h2><a class="reference external" href="https://app.cloudskew.com/">https://app.cloudskew.com/</a></h2> +<p>Desenhar projetos de cloud e afins</p> +</div> +<div class="section" id="https-lottiefiles-com"> +<h2><a class="reference external" href="https://lottiefiles.com/">https://lottiefiles.com/</a></h2> +<p>Veja por si mesmo</p> +</div> +Desenvolvendo apps para o FirefoxOS (Parte 1)2014-09-02T19:00:00-03:002014-09-02T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2014-09-02:/pt/desenvolvendo-app-firefoxos.html<h3>Requisitos mínimos?</h3> +<p>Para seguir este tutorial você precisará do <a href="http://nodejs.org/">Nodejs</a>. Utilizaremos ele para automatizar algumas tarefas, como a criação do nosso projeto e até mesmo o empacotamento da app. Estas automatizações se darão pela utilização de algumas aplicações como o <a href="http://yeoman.io/">Yeoman</a> e o <a href="http://gruntjs.com/">Grunt</a> .</p> +<p>Também será necessário o emulador do …</p><h3>Requisitos mínimos?</h3> +<p>Para seguir este tutorial você precisará do <a href="http://nodejs.org/">Nodejs</a>. Utilizaremos ele para automatizar algumas tarefas, como a criação do nosso projeto e até mesmo o empacotamento da app. Estas automatizações se darão pela utilização de algumas aplicações como o <a href="http://yeoman.io/">Yeoman</a> e o <a href="http://gruntjs.com/">Grunt</a> .</p> +<p>Também será necessário o emulador do <a href="https://www.mozilla.org/pt-BR/firefox/os/">FirefoxOS</a>, ele roda através do seu navegador Firefox. Para instalá-lo basta ir no menu <code>Ferramentas &gt; Desenvolvedor web &gt; App Manager</code>, nesta tela basta tentar iniciar o emulador, se não possuir um já instalado, você será solicitado a fazê-lo. Neste tutorial irei utilizar a versão 1.4.</p> +<h3>Preparando o ambiente</h3> +<p>Tendo o Node instalado, vamos instalar o yeoman e o gerador de app para Firefox OS. Atenção para o parâmetro '-g' no processo de instalação, com ele os seus pacotes serão instalados globalmente, e não só para a pasta em que esta o prompt.</p> +<div class="highlight"><pre><span></span><code><span class="err">npm install -g yo</span> +<span class="err">npm install -g generator-firefoxos-app</span> +</code></pre></div> + +<p>Com ambos os pacotes acima instalados, vamos dar início a criação da app. No seu diretório de projetos ou onde desejar criar a app chama o generator instalado.</p> +<div class="highlight"><pre><span></span><code><span class="err">yo firefoxos-app</span> +</code></pre></div> + +<p>Uma vez chamado esse generator, o mesmo irá fazer alguns questionamentos, o primeiro é claro será o nome da sua aplicação, seguido da descrição e o nome do desenvolvedor.</p> +<p>Após a execução do generator, você já terá uma estrutura para desenvolvimento pronta, inclusive com um html inicial, com todas as dependências já instaladas. Vale ressaltar agora algumas tarefas disponíveis no Gruntfile.</p> +<ul> +<li>Default: Irá gerar o pacote de distribuição</li> +<li>Test: Até a presente versão do generator (0.1.3) este processo irá simplesmente rodar o validador jsHint</li> +<li>Server: Irá disponibilizar na porta 9001 um simples servidor para testar a sua app</li> +</ul> +<p>Vamos testar a nossa app. Para tal, rode o comando <code>grunt server</code> e acesse no seu navegador <code>localhost:9001</code> e devemos ver a seguinte app. Caso nenhuma página seja exibida, revise os passos ateriores e verifique se nenhum erro ocorreu.</p> +<p><img alt="App inicial" src="/images/app_inicial.png"></p> +<p>Vale ressaltar que a sua app toda estará dentro de uma pasta também chamada <code>app</code>. Nela você encontrará os seus arquivos .html, .js, .css e demais. Antes de começarmos a codificar a nossa app, vamos ver como se instala a mesma.</p> +<h3>Instalando a app</h3> +<p>Para fins de teste, não é necessário rodar o comando <code>grunt</code>, sendo que ele irá testar o JS e compactar tudo em um arquivo .zip, basta apontar a instalação para a pasta <code>app</code> dentro do seu projeto. "Mas como eu faço isto?".</p> +<p>Indo novamente na <code>App Manager</code>, clicando na lateral esquerda, onde indica "Aplicativos", teremos então disponível no inferior da tela duas opções, vamos nos ater a utilizar a primeira (<code>Adicionar aplicativo hospedado</code>).</p> +<p>Clicando nesta opção vamos navegar até a pasta da app e clicar selecionada. Pronto.</p> +<p>Simples de se instalar, não acha? O Resultado final deve ser semelhante ao abaixo.</p> +<p><img alt="App inicial" src="/images/app_visual_1.png"></p> +<h3>Acessando uma API</h3> +<p>Quando vamos programar algo mais complexo, geralmente vamos utilizar algo como, câmera, rede, lista de contatos, armazenamento e outras possibilidades. Para utilizarmos essas APIs, precisamos - assim como no desenvolvimento para android - especificar para o usuário no momento de instalação. Estes dados de acesso ficam no arquivo <code>manifes.webapp</code>, se você ainda não deu uma olhada neste arquivo, é nele que fica armazenado dados da app, como nome, descrição, versão, localização de ícones e é claro as permissões que a mesma requer.</p> +<p>As permissões ficam na propriedade permissions, na forma de <code>"chave" : True</code>. Algumas das apis são:</p> +<ul> +<li>câmera</li> +<li>contacts</li> +<li>desktop-notification</li> +<li>storage</li> +</ul> +<p>Cada permissão vai mudar o tipo de app que você esta desenvolvendo, mas aí eu sugiro ler mais na MDN <a href="https://developer.mozilla.org/en-US/Apps/Build/App_permissions">aqui</a>. Esse é o básico para iniciar no desenvolvimento de app para FirefoxOS. Na parte dois, vou começar a passar um pouco de código.</p>Editando o Admin do Django2014-05-15T18:00:00-03:002014-05-15T18:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2014-05-15:/pt/editando-o-admin-do-django.html<p>Este artigo foi re-postado no grupo <a class="reference external" href="http://pythonclub.com.br/editando-o-admin-do-django.html">PythonClub</a>. Vamos falar um pouco sobre como customizar o admin do Django. Primeiramente porque? A resposta é bem simples, quero mostrar algo para o usuário sem que ele precise entrar nas apps e fazer alguma consulta para então tomar alguma ação. Alguns exêmplos para …</p><p>Este artigo foi re-postado no grupo <a class="reference external" href="http://pythonclub.com.br/editando-o-admin-do-django.html">PythonClub</a>. Vamos falar um pouco sobre como customizar o admin do Django. Primeiramente porque? A resposta é bem simples, quero mostrar algo para o usuário sem que ele precise entrar nas apps e fazer alguma consulta para então tomar alguma ação. Alguns exêmplos para isto seriam:</p> +<blockquote> +<ul class="simple"> +<li>Exibir as vendas do mês em forma de gráfico por região do país</li> +<li>Exibir os últimos comentários adicionados</li> +<li>Exibir log dos ultimos usuários cadastrados</li> +</ul> +</blockquote> +<p>O que faremos aqui será exibir os últimos comentários ainda não liberados de um sistema de blog. Vale lembrar que aqui não discutiremos sobre os primeiros passos da aplicação. Para seguirmos adiante, vamos assumir que já temos um projeto básico com uma estrutura simples, abaixo a estrutura inicial do nosso projeto.</p> +<div class="highlight"><pre><span></span>../blog/ +├── core +│ ├── __init__.py +│ ├── admin.py +│ ├── models.py +│ ├── tests.py +│ └── views.py +├── blog +│ ├── __init__.py +│ ├── settings.py +│ ├── urls.py +│ └── wsgi.py +└── manage.py +</pre></div> +<p>Para iniciarmos, precisamos da nossa tabela de comentários, vamos usar a mais simples e básica o possível.</p> +<table border="1" class="docutils"> +<colgroup> +<col width="50%" /> +<col width="50%" /> +</colgroup> +<thead valign="bottom"> +<tr><th class="head">Campo</th> +<th class="head">Tipo</th> +</tr> +</thead> +<tbody valign="top"> +<tr><td>nome</td> +<td>Varchar(30)</td> +</tr> +<tr><td>texto</td> +<td>Text</td> +</tr> +<tr><td>liberado</td> +<td>Boolean</td> +</tr> +<tr><td>data</td> +<td>Date</td> +</tr> +</tbody> +</table> +<p>Vamos seguir adiante e alterar a página inicial do admin para listar os últimos comentários de um simples sistema de blog. Para comerçar a editar o admin, precisamos inicialmente copiar o template que desejamos para a pasta uma pasta <cite>admin</cite> dentro ta pasta de templates do nosso projeto. Isto porque o Admin, não passa de uma app como outra qualquer, portanto o sistema de herança vai funcionar aqui, carregamento prioritariamente o seu template. Você pode conseguir o template que desejar (no nosso caso o index.html) dentro do projeto do Django mesmo, no meu caso &quot;C:\Django-1.6.3\django\contrib\admin\templates\admin&quot;.</p> +<div class="highlight"><pre><span></span>../blog/ +├── templates +│ ├── admin +│ │ └── index.html +├── core +</pre></div> +<p>Tire um tempo e brinque um pouco com este template e veja o que acontece se você alterar algumas coisa. Para adicionarmos a nossa listagem, vamos adicionar um painel lateral, para tal vamos adicionar o código abaixo antes do fechamento da ultima tag div. Nele podemos ver uma chamada para uma template_tag, portanto precisamos carrega-la no topo do template.</p> +<div class="highlight"><pre><span></span>{% load comentarios_tag %} +... +... +... +<span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">&quot;module&quot;</span> <span class="na">id</span><span class="o">=</span><span class="s">&quot;ultimos-comentarios&quot;</span><span class="p">&gt;</span> + <span class="p">&lt;</span><span class="nt">h2</span><span class="p">&gt;</span>Ultimos Comentários<span class="p">&lt;/</span><span class="nt">h2</span><span class="p">&gt;</span> + <span class="p">&lt;</span><span class="nt">h3</span><span class="p">&gt;</span>Liberar<span class="p">&lt;/</span><span class="nt">h3</span><span class="p">&gt;</span> + {% comentarios_n_liberados %} +<span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span> +</pre></div> +<p>Esta template trata-se da responsável por fazer a consulta na base de dados e renderizar a nossa lista, portanto ela é uma 'inclusion tag'. Se você não esta familiarizado com 'template tags', talvez queira dar uma olhada na <a class="reference external" href="https://docs.djangoproject.com/en/dev/howto/custom-template-tags/">documentação do django</a>.</p> +<p>Vamos então criar nossa template tag 'comentarios_n_liberados'. Primeiro devemos criar uma pasta chamada templatetags, dentro da nossa app core. Dentro ta pasta vamos inicializar um pacote python e criar o arquivo comentarios_tag.py. Nele precisamos declarar nosso metodo que deve se chamar 'comentarios_n_liberados' e nele fazer uma simples consulta ao banco buscando os comentários não liberados e por fim registrar a tag apontando para o template que será renderizado. Abaixo o código mais explicado.</p> +<div class="livros"> + <div class="recomendacoes">Recomendações</div> + <a rel="noopener nofollow" href="https://www.amazon.com.br/gp/product/8575225081/ref=as_li_ss_il?ie=UTF8&linkCode=li2&tag=sipmann-20&linkId=c17fa3ac84e734741a3761e874d7d286" target="_blank"><img border="0" src="//ws-na.amazon-adsystem.com/widgets/q?_encoding=UTF8&ASIN=8575225081&Format=_SL160_&ID=AsinImage&MarketPlace=BR&ServiceVersion=20070822&WS=1&tag=sipmann-20" ></a><img src="https://ir-br.amazon-adsystem.com/e/ir?t=sipmann-20&l=li2&o=33&a=8575225081" alt="Livro Pense em Python na Amazon" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /> + <a rel="noopener nofollow" href="https://www.amazon.com.br/gp/product/B074ZTLKHB/ref=as_li_ss_il?ie=UTF8&linkCode=li2&tag=sipmann-20&linkId=e2f37c07da2dc4111ae47854b205d01a" target="_blank"><img border="0" src="//ws-na.amazon-adsystem.com/widgets/q?_encoding=UTF8&ASIN=B074ZTLKHB&Format=_SL160_&ID=AsinImage&MarketPlace=BR&ServiceVersion=20070822&WS=1&tag=sipmann-20" ></a><img src="https://ir-br.amazon-adsystem.com/e/ir?t=sipmann-20&l=li2&o=33&a=B074ZTLKHB" alt="Livro Curso Intensivo de Python na Amazon" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /> +</div><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django</span> <span class="kn">import</span> <span class="n">template</span> +<span class="kn">from</span> <span class="nn">core</span> <span class="kn">import</span> <span class="n">models</span> + +<span class="c1">#Carrega o registro de template tags</span> +<span class="n">register</span> <span class="o">=</span> <span class="n">template</span><span class="o">.</span><span class="n">Library</span><span class="p">()</span> + +<span class="c1">#Registra o metodo a seguir como uma inclusion_tag indicando o template a ser renderizad</span> +<span class="nd">@register</span><span class="o">.</span><span class="n">inclusion_tag</span><span class="p">(</span><span class="s1">&#39;comentarios_n_liberados.html&#39;</span><span class="p">)</span> +<span class="k">def</span> <span class="nf">comentarios_n_liberados</span><span class="p">():</span> + <span class="n">comentarios</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">comentario</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">liberado</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span><span class="o">.</span><span class="n">order_by</span><span class="p">(</span><span class="s1">&#39;data&#39;</span><span class="p">)[</span><span class="mi">0</span><span class="p">:</span><span class="mi">5</span><span class="p">]</span> + <span class="k">return</span> <span class="p">{</span> <span class="s1">&#39;comentarios&#39;</span> <span class="p">:</span> <span class="n">comentarios</span> <span class="p">}</span> +</pre></div> +<p>Abaixo o html do nosso template a ser renderizado, este deve estar dentro da pasta templates da nossa app core.</p> +<div class="highlight"><pre><span></span>{% if not comentarios %} + <span class="p">&lt;</span><span class="nt">p</span><span class="p">&gt;</span>Nenhum comentário novo<span class="p">&lt;/</span><span class="nt">p</span><span class="p">&gt;</span> +{% else %} + <span class="p">&lt;</span><span class="nt">ul</span><span class="p">&gt;</span> + {% for c in comentarios %} + <span class="p">&lt;</span><span class="nt">li</span> <span class="na">class</span><span class="o">=</span><span class="s">&quot;addlink&quot;</span><span class="p">&gt;</span> + <span class="p">&lt;</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">&quot;{{ c.id }}&quot;</span><span class="p">&gt;</span>{{ c.texto|truncatechars:30 }}<span class="p">&lt;/</span><span class="nt">a</span><span class="p">&gt;</span> + <span class="p">&lt;/</span><span class="nt">li</span><span class="p">&gt;</span> + {% endfor %} + <span class="p">&lt;/</span><span class="nt">ul</span><span class="p">&gt;</span> +{% endif %} +</pre></div> +<p>Com tudo isto feito, basta subir o seu servidor e ver o resultado final, que pode ser visto na imagem abaixo.</p> +<img alt="Resultado final" src="images/admin_modificado.png" /> +<p>Lembrando que aqui apenas mostrei como modificar o index do admin, para apenas listar dados do banco, mas você pode ir muito mais além. Abaixo fica a estrutura de diretórios final e um link para download do projeto funcionando.</p> +<div class="highlight"><pre><span></span>../blog/ +├── core +│ ├── templates +│ │ └── comentarios_n_liberados.html +│ ├── templatetag +│ │ └── comentarios_tag.py +│ ├── __init__.py +│ ├── admin.py +│ ├── models.py +│ ├── tests.py +│ └── views.py +├── blog +│ ├── __init__.py +│ ├── settings.py +│ ├── urls.py +│ └── wsgi.py +├── templates +│ ├── admin +│ │ └── index.html +└── manage.py +</pre></div> +<p>Espero que tenham gostado, criticas/sugestões são bem-vindas. <a class="reference external" href="https://github.com/sipmann/editando-django-admin">Fontes do Projeto</a></p> + \ No newline at end of file diff --git a/pt/feeds/all-pt.atom.xml.gz b/pt/feeds/all-pt.atom.xml.gz new file mode 100644 index 000000000..4579b6cd7 Binary files /dev/null and b/pt/feeds/all-pt.atom.xml.gz differ diff --git a/pt/feeds/all.atom.xml b/pt/feeds/all.atom.xml new file mode 100644 index 000000000..811483e5d --- /dev/null +++ b/pt/feeds/all.atom.xml @@ -0,0 +1,1298 @@ + +Sipmannhttps://www.sipmann.com/pt/2020-12-21T13:30:00-03:00Monitorando restarts do MySQL com PowerShell2020-12-21T13:30:00-03:002020-12-21T13:30:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-12-21:/pt/monitoring-mysql-restarts-with-powershell.html<p>Bom, chegou a hora para mais um script PowerShell. Se você ainda não viu os outros, de uma olhada no link abaixo.</p> +<ul> +<li><a href="https://www.sipmann.com/pt/monitoring-mysql-replication-with-powershell.html">Monitorando status de replicação do MySQL com PowerShell</a></li> +</ul> +<p>Este aqui é um script bem simples, mas novamente, se seu cliente não possui um servidor Zabbix ou não permite …</p><p>Bom, chegou a hora para mais um script PowerShell. Se você ainda não viu os outros, de uma olhada no link abaixo.</p> +<ul> +<li><a href="https://www.sipmann.com/pt/monitoring-mysql-replication-with-powershell.html">Monitorando status de replicação do MySQL com PowerShell</a></li> +</ul> +<p>Este aqui é um script bem simples, mas novamente, se seu cliente não possui um servidor Zabbix ou não permite que você configure um para realizar este monitoramento, um conjunto de scripts pode ser bem útil. Primeiramente nós executamos uma query báscia <code>SHOW GLOBAL STATUS LIKE 'Uptime'</code>, com ela nós conseguimos capturar exatamente o que nós estamos procurando.</p> +<p>Se por alguma razão o comando falhar (verificamos atravez da variábel global <code>$lastExitCode</code>), nós mandamos um e-mail lhe avisando sobre o problema ocorrido.</p> +<p>E então, nós chegamos à parte onde fazemos o parse do valor obtido, esta parte é bem similar ao parse que codificamos no primeiro post sobre monitoramento utilizando PowerShell. Nós basicamentes procuramos pela linha contendo <code>Value</code>, separamos por espaço e então parseamos a segunda posição em um inteiro. Então tudo que precisamos fazer é verificar se o valor parseado é menor que o nosso threshold, se for menor, nós mandamos um e-mail.</p> +<div class="highlight"><pre><span></span><code><span class="nv">$MailFrom</span> <span class="p">=</span> <span class="s1">&#39;maurio[at]sipmann.com&#39;</span> +<span class="nv">$MailTo</span> <span class="p">=</span> <span class="s1">&#39;mauricio[at]sipmann.com&#39;</span> +<span class="nv">$MysqlHost</span> <span class="p">=</span> <span class="s1">&#39;127.0.0.1&#39;</span> +<span class="nv">$MysqlUser</span> <span class="p">=</span> <span class="s1">&#39;root&#39;</span> +<span class="nv">$MysqlPass</span> <span class="p">=</span> <span class="s1">&#39;123&#39;</span> + + +<span class="nv">$data</span> <span class="p">=</span> <span class="p">$(</span><span class="n">mysql</span> <span class="n">-h</span> <span class="nv">$MysqlHost</span> <span class="n">-u</span> <span class="nv">$MysqlUser</span> <span class="n">-p</span><span class="s2">&quot;$MysqlPass&quot;</span> <span class="n">-e</span> <span class="s2">&quot;SHOW GLOBAL STATUS LIKE &#39;Uptime&#39; \G&quot;</span><span class="p">)</span> + +<span class="cm">&lt;# Unable to execute the sql Command #&gt;</span> +<span class="k">if</span> <span class="p">(</span><span class="nv">$lastExitCode</span> <span class="o">-eq</span> <span class="n">1</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Send-MailMessage</span> <span class="n">-To</span> <span class="nv">$MailTo</span> <span class="n">-From</span> <span class="nv">$MailFrom</span> <span class="n">-Subject</span> <span class="s1">&#39;Connection problem&#39;</span> <span class="n">-bodyAsHtml</span> <span class="s2">&quot;Connection problem on host ${MysqlHost}&quot;</span> <span class="n">-Credential</span> <span class="nb">Get-Credential</span> <span class="n">-SmtpServer</span> <span class="s1">&#39;smtp.office365.com&#39;</span> <span class="n">-Port</span> <span class="n">587</span> <span class="n">-UseSsl</span> + <span class="n">exit</span> +<span class="p">}</span> + +<span class="nv">$UpTime</span> <span class="p">=</span> <span class="no">[int]</span><span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Value:&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> + +<span class="cm">&lt;# If the uptime is lower then 20 minutes #&gt;</span> +<span class="k">if</span> <span class="p">(</span><span class="nv">$UpTime</span> <span class="o">-lt</span> <span class="n">1200</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Send-MailMessage</span> <span class="n">-To</span> <span class="nv">$MailTo</span> <span class="n">-From</span> <span class="nv">$MailFrom</span> <span class="n">-Subject</span> <span class="s2">&quot;MySQL Restarted&quot;</span> <span class="n">-bodyAsHtml</span> <span class="s2">&quot;MySQL host ${MysqlHost} restarted less than 20 minutes ago&quot;</span> <span class="n">-Credential</span> <span class="nb">Get-Credential</span> <span class="n">-SmtpServer</span> <span class="s1">&#39;smtp.office365.com&#39;</span> <span class="n">-Port</span> <span class="n">587</span> <span class="n">-UseSsl</span> +<span class="p">}</span> +</code></pre></div> + +<p>Este script (e os outros que eu utilizo) estão disponíveis no meu GitHub <a href="https://github.com/sipmann/PowerShellScripts">aqui</a>. Tenha em mente que os scripts localizados no GitHub, são um pouco diferentes do que exibido aqui. Espero que tenha achado útil.</p>Monitoring MySQL restarts with PowerShell2020-12-21T13:30:00-03:002020-12-21T13:30:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-12-21:/en/monitoring-mysql-restarts-with-powershell.html<p>Hey folks, it's time for another PowerShell script. If you haven't seen the other ones, check the links below.</p> +<ul> +<li><a href="https://www.sipmann.com/en/monitoring-mysql-replication-with-powershell.html">Monitoring MySQL replication with PowerShell</a></li> +</ul> +<p>Well, this one it's a pretty simple script, but again, if your customer doesn't have a Zabbix server or doesn't allow you to setup one to …</p><p>Hey folks, it's time for another PowerShell script. If you haven't seen the other ones, check the links below.</p> +<ul> +<li><a href="https://www.sipmann.com/en/monitoring-mysql-replication-with-powershell.html">Monitoring MySQL replication with PowerShell</a></li> +</ul> +<p>Well, this one it's a pretty simple script, but again, if your customer doesn't have a Zabbix server or doesn't allow you to setup one to do the monitoring, a set of scripts can be handy. We start executing some basic query <code>SHOW GLOBAL STATUS LIKE 'Uptime'</code>, with that we'll get exactly what we're looking for.</p> +<p>If for some reason, the command fails (watch for the "global" variable called <code>$lastExitCode</code>), we send an e-mail telling you about that connection problem.</p> +<p>And then, we get to the part where we parse the value, this one is pretty similar to the parse we did on the first post about using PowerShell to monitor MySQL. But we basically look for the Value line, split it by space and then parse the second position to an integer. And then all we have to do is check if the uptime is lower than our threshold, if it is we send an e-mail.</p> +<div class="highlight"><pre><span></span><code><span class="nv">$MailFrom</span> <span class="p">=</span> <span class="s1">&#39;maurio[at]sipmann.com&#39;</span> +<span class="nv">$MailTo</span> <span class="p">=</span> <span class="s1">&#39;mauricio[at]sipmann.com&#39;</span> +<span class="nv">$MysqlHost</span> <span class="p">=</span> <span class="s1">&#39;127.0.0.1&#39;</span> +<span class="nv">$MysqlUser</span> <span class="p">=</span> <span class="s1">&#39;root&#39;</span> +<span class="nv">$MysqlPass</span> <span class="p">=</span> <span class="s1">&#39;123&#39;</span> + + +<span class="nv">$data</span> <span class="p">=</span> <span class="p">$(</span><span class="n">mysql</span> <span class="n">-h</span> <span class="nv">$MysqlHost</span> <span class="n">-u</span> <span class="nv">$MysqlUser</span> <span class="n">-p</span><span class="s2">&quot;$MysqlPass&quot;</span> <span class="n">-e</span> <span class="s2">&quot;SHOW GLOBAL STATUS LIKE &#39;Uptime&#39; \G&quot;</span><span class="p">)</span> + +<span class="cm">&lt;# Unable to execute the sql Command #&gt;</span> +<span class="k">if</span> <span class="p">(</span><span class="nv">$lastExitCode</span> <span class="o">-eq</span> <span class="n">1</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Send-MailMessage</span> <span class="n">-To</span> <span class="nv">$MailTo</span> <span class="n">-From</span> <span class="nv">$MailFrom</span> <span class="n">-Subject</span> <span class="s1">&#39;Connection problem&#39;</span> <span class="n">-bodyAsHtml</span> <span class="s2">&quot;Connection problem on host ${MysqlHost}&quot;</span> <span class="n">-Credential</span> <span class="nb">Get-Credential</span> <span class="n">-SmtpServer</span> <span class="s1">&#39;smtp.office365.com&#39;</span> <span class="n">-Port</span> <span class="n">587</span> <span class="n">-UseSsl</span> + <span class="n">exit</span> +<span class="p">}</span> + +<span class="nv">$UpTime</span> <span class="p">=</span> <span class="no">[int]</span><span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Value:&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> + +<span class="cm">&lt;# If the uptime is lower then 20 minutes #&gt;</span> +<span class="k">if</span> <span class="p">(</span><span class="nv">$UpTime</span> <span class="o">-lt</span> <span class="n">1200</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Send-MailMessage</span> <span class="n">-To</span> <span class="nv">$MailTo</span> <span class="n">-From</span> <span class="nv">$MailFrom</span> <span class="n">-Subject</span> <span class="s2">&quot;MySQL Restarted&quot;</span> <span class="n">-bodyAsHtml</span> <span class="s2">&quot;MySQL host ${MysqlHost} restarted less than 20 minutes ago&quot;</span> <span class="n">-Credential</span> <span class="nb">Get-Credential</span> <span class="n">-SmtpServer</span> <span class="s1">&#39;smtp.office365.com&#39;</span> <span class="n">-Port</span> <span class="n">587</span> <span class="n">-UseSsl</span> +<span class="p">}</span> +</code></pre></div> + +<p>This script (and the other ones I use) is available at my GitHub <a href="https://github.com/sipmann/PowerShellScripts">here</a>. Keep in mind that the ones on the GitHub repo, are a little different from here.</p>Trocando a senha de um usuário do MySQL sem downtime da aplicação2020-12-09T13:40:00-03:002020-12-09T13:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-12-09:/pt/mysql-dual-password-functionality.html<p>Você deseja trocar a senha de um usuário do MySQL que está sendo utilizado por uma aplicação e não sofrer nenhum downtime? Bom, a versão 8.0.14 do MySQL foi liberada com uma feature chamada <a href="https://dev.mysql.com/doc/refman/8.0/en/password-management.html#dual-passwords">Dual Password Support</a>, com esta feature você pode alterar a senha de um usuário …</p><p>Você deseja trocar a senha de um usuário do MySQL que está sendo utilizado por uma aplicação e não sofrer nenhum downtime? Bom, a versão 8.0.14 do MySQL foi liberada com uma feature chamada <a href="https://dev.mysql.com/doc/refman/8.0/en/password-management.html#dual-passwords">Dual Password Support</a>, com esta feature você pode alterar a senha de um usuário mantendo a anterior ainda funcionando como uma forma de "backup". Desta forma, você ainda conseguirá autenticar com o usuário utilizando tanto a nova senha, quanto a anterior. Com isto, o seu processo de troca de senha fica algo como:</p> +<p>1) Troque a senha mantendo a anterior;</p> +<p>2) Faça o Deploy da nova configuração na sua aplicação/cluster;</p> +<p>3) Descarte a senha anterior.</p> +<p>Para alterar a senha mantendo a anterior, você deve rodar o seguinte comando:</p> +<div class="highlight"><pre><span></span><code><span class="k">ALTER</span> <span class="n">USER</span> <span class="s1">&#39;appuser&#39;</span><span class="o">@</span><span class="s1">&#39;localhost&#39;</span> <span class="n">IDENTIFIED</span> <span class="k">BY</span> <span class="s1">&#39;new_password&#39;</span> <span class="n">RETAIN</span> <span class="n">CURRENT</span> <span class="n">PASSWORD</span><span class="p">;</span> +</code></pre></div> + +<p>Para descartar a senha antiga, rode o seguinte:</p> +<div class="highlight"><pre><span></span><code><span class="k">ALTER</span> <span class="n">USER</span> <span class="s1">&#39;appuser&#39;</span><span class="o">@</span><span class="s1">&#39;localhost&#39;</span> <span class="n">DISCARD</span> <span class="n">OLD</span> <span class="n">PASSWORD</span><span class="p">;</span> +</code></pre></div> + +<p>E pronto. Espero que isto lhe ajude a evitar downtimes e dores de cabeça :)</p>Changing a MySQL user password across multiple application instances without downtime2020-12-09T13:40:00-03:002020-12-09T13:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-12-09:/en/mysql-dual-password-functionality.html<p>Do you need to change the password of a MySQL user that it's being used in an application, and can't allow a single downtime? Well, MySQL 8.0.14 came with a feature called <a href="https://dev.mysql.com/doc/refman/8.0/en/password-management.html#dual-passwords">Dual Password Support</a>, with it you can change the password keeping the previous password as a …</p><p>Do you need to change the password of a MySQL user that it's being used in an application, and can't allow a single downtime? Well, MySQL 8.0.14 came with a feature called <a href="https://dev.mysql.com/doc/refman/8.0/en/password-management.html#dual-passwords">Dual Password Support</a>, with it you can change the password keeping the previous password as a kind of backup. That way you still can log in using the old password or can start using the new one. With that, the password change workflow it's the following.</p> +<p>1) Change password keeping the old one;</p> +<p>2) Deploy the new config to your app/cluster;</p> +<p>3) Discard the old password.</p> +<p>To change the password and keep the old one, you have the following command.</p> +<div class="highlight"><pre><span></span><code><span class="k">ALTER</span> <span class="n">USER</span> <span class="s1">&#39;appuser&#39;</span><span class="o">@</span><span class="s1">&#39;localhost&#39;</span> <span class="n">IDENTIFIED</span> <span class="k">BY</span> <span class="s1">&#39;new_password&#39;</span> <span class="n">RETAIN</span> <span class="n">CURRENT</span> <span class="n">PASSWORD</span><span class="p">;</span> +</code></pre></div> + +<p>To discard the old one, run the following.</p> +<div class="highlight"><pre><span></span><code><span class="k">ALTER</span> <span class="n">USER</span> <span class="s1">&#39;appuser&#39;</span><span class="o">@</span><span class="s1">&#39;localhost&#39;</span> <span class="n">DISCARD</span> <span class="n">OLD</span> <span class="n">PASSWORD</span><span class="p">;</span> +</code></pre></div> + +<p>And you are done. Hope you find it as useful as I :)</p>Apache Nifi JSON to SQL removendo underline2020-12-02T14:00:00-03:002020-12-02T14:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-12-02:/pt/apache-nifi-json-to-sql-replacing-underscore.html<p>Recentemente eu estava desenvolvendo alguns processos de ETL com o Apache NiFi. Mas após alguns minutos desenhando o meu fluxo, eu vi um comportamento estranho do componente ConvertJSONToSQL, que estava substituindo os underline ('_') do nome de um campo utilizado na condição da SQL (eu estava preparando um UPDATE). Aquilo …</p><p>Recentemente eu estava desenvolvendo alguns processos de ETL com o Apache NiFi. Mas após alguns minutos desenhando o meu fluxo, eu vi um comportamento estranho do componente ConvertJSONToSQL, que estava substituindo os underline ('_') do nome de um campo utilizado na condição da SQL (eu estava preparando um UPDATE). Aquilo estava estranho, uma vez que na definição do SET da SQL, o nome do campo permanecia inalterado. Depois de algumas pesquisas, achei uma doc que a propriedade (veja abaixo) <code>Translate Field Names</code> era a responsável por este comportamento estranho.</p> +<p><img alt="Apache NiFi JSONToSQL config" src="/images/apache_nifi_jsontosql.png"></p> +<p>Antes de definir a propriedade como <strong>FALSE</strong>, esteja ciente que as propriedades do seu JSON devem ser exatamente iguais aos nomes dos campos da sua tabela.</p>Apache Nifi JSON to SQL Replacing underscore2020-12-02T14:00:00-03:002020-12-02T14:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-12-02:/en/apache-nifi-json-to-sql-replacing-underscore.html<p>Recently I was doing some ETL with Apache NiFi. But after a few minutes of drawing my flow, I saw that the component ConvertJSONToSQL was replacing the underscore ('_') from the field name in the where condition (I was preparing an Update SQL). That was weird because, at the set …</p><p>Recently I was doing some ETL with Apache NiFi. But after a few minutes of drawing my flow, I saw that the component ConvertJSONToSQL was replacing the underscore ('_') from the field name in the where condition (I was preparing an Update SQL). That was weird because, at the set statement, the field name was kept intact. After some research, I found that the property (see bellow) <code>Translate Field Names</code> was responsible for that weird replacement.</p> +<p><img alt="Apache NiFi JSONToSQL config" src="/images/apache_nifi_jsontosql.png"></p> +<p>Before setting it to <strong>FALSE</strong>, be aware that the properties on your JSON data must match exactly the name of your fields.</p>Bloqueando um usuário do SQL Server baseado em uma tabela de horários2020-11-14T07:00:00-03:002020-11-14T07:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-11-14:/pt/blocking-user-on-sql-server-based-on-schedule.html<p>Ok, algum tempo atrás, eu postei sobre como você pode impor limites às conexões do SQL Server utilizando o <a href="https://www.sipmann.com/limiting-connection-resources-sql-server.html#.X6Cz8IhKhPY">Resource Governor</a>. Mas, e se você não pode utilizar ele? Você sempre pode bloquear logins usando uma trigger, mas eu não gosto da ideia de ter um select rodando a cada …</p><p>Ok, algum tempo atrás, eu postei sobre como você pode impor limites às conexões do SQL Server utilizando o <a href="https://www.sipmann.com/limiting-connection-resources-sql-server.html#.X6Cz8IhKhPY">Resource Governor</a>. Mas, e se você não pode utilizar ele? Você sempre pode bloquear logins usando uma trigger, mas eu não gosto da ideia de ter um select rodando a cada login. Então, eu cheguei a esta solução, utilizando uma stored procedure, uma tabela e o Agent.</p> +<p>A ideia principal é armazenar o horário em que um usuário deve ser bloqueado pelo Agent. Abaixo você pode ver a criação da tabela:</p> +<div class="highlight"><pre><span></span><code><span class="k">CREATE</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"> </span><span class="p">(</span><span class="w"></span> +<span class="w"> </span><span class="n">Id</span><span class="w"> </span><span class="nc">INT</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">LoginName</span><span class="w"> </span><span class="nc">NVARCHAR</span><span class="p">(</span><span class="mi">100</span><span class="p">)</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">HrInicio</span><span class="w"> </span><span class="nc">TIME</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"> </span><span class="cm">/* horário de inicio do bloqueio */</span><span class="w"></span> +<span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="nc">TIME</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"> </span><span class="cm">/*horário de termino */</span><span class="w"></span> +<span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="nc">INT</span><span class="w"> </span><span class="k">DEFAULT</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="cm">/* 0 = desbloqueado, 1 = bloqueado */</span><span class="w"></span> +<span class="w"> </span><span class="k">PRIMARY</span><span class="w"> </span><span class="k">KEY</span><span class="w"> </span><span class="p">(</span><span class="n">Id</span><span class="p">)</span><span class="w"></span> +<span class="p">);</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> + +<span class="cm">/* regra para Não bloquear o usuário SA */</span><span class="w"></span> +<span class="k">ALTER</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"></span> +<span class="w"> </span><span class="k">ADD</span><span class="w"> </span><span class="k">CONSTRAINT</span><span class="w"> </span><span class="n">chk_users</span><span class="w"> </span><span class="k">CHECK</span><span class="w"> </span><span class="p">(</span><span class="n">LoginName</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;sa&#39;</span><span class="p">));</span><span class="w"></span> + +<span class="k">ALTER</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"></span> +<span class="w"> </span><span class="k">ADD</span><span class="w"> </span><span class="k">CONSTRAINT</span><span class="w"> </span><span class="n">chk_hora_final_maior</span><span class="w"> </span><span class="k">CHECK</span><span class="w"> </span><span class="p">(</span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="n">HrInicio</span><span class="p">);</span><span class="w"></span> + +<span class="k">ALTER</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"></span> +<span class="w"> </span><span class="k">ADD</span><span class="w"> </span><span class="k">CONSTRAINT</span><span class="w"> </span><span class="n">chk_status_bloqueio</span><span class="w"> </span><span class="k">CHECK</span><span class="w"> </span><span class="p">(</span><span class="n">Bloqueado</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">));</span><span class="w"></span> + +<span class="k">CREATE</span><span class="w"> </span><span class="k">SEQUENCE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">seq_HorariosBloqueio</span><span class="w"> </span><span class="k">START</span><span class="w"> </span><span class="k">WITH</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="n">INCREMENT</span><span class="w"> </span><span class="k">BY</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +</code></pre></div> + +<p>Depois de criar a tabela, vamos verificar a procedure que vai fazer todo o trabalho de habilitar/desabilitar os usuários. Fique ciente que, nesta procedure, eu defini o nome do banco onde a tabela está armazenada. Você pode substituir o nome <code>DBATOOLS</code> pelo o nome da sua base.</p> +<div class="highlight"><pre><span></span><code><span class="k">IF</span><span class="w"> </span><span class="nf">OBJECT_ID</span><span class="p">(</span><span class="s1">&#39;dbo.sp_ValidarLogin&#39;</span><span class="p">)</span><span class="w"> </span><span class="k">IS</span><span class="w"> </span><span class="k">NULL</span><span class="w"></span> +<span class="w"> </span><span class="k">EXEC</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;CREATE PROCEDURE dbo.sp_ValidarLogin AS RETURN 0;&#39;</span><span class="p">);</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> + +<span class="k">CREATE</span><span class="w"> </span><span class="ow">OR</span><span class="w"> </span><span class="k">ALTER</span><span class="w"> </span><span class="k">PROC</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">sp_ValidarLogin</span><span class="w"></span> +<span class="k">AS</span><span class="w"> </span><span class="k">BEGIN</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="nc">NVARCHAR</span><span class="p">(</span><span class="mi">100</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="nc">TIME</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="k">SET</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nf">CAST</span><span class="p">(</span><span class="nf">GETDATE</span><span class="p">()</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="nc">TIME</span><span class="p">);</span><span class="w"></span> + +<span class="w"> </span><span class="cm">/* Bloqueia os que ainda não estiverem bloqueados de acordo com a hora atual */</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="n">block_cursor</span><span class="w"> </span><span class="nc">CURSOR</span><span class="w"></span> +<span class="w"> </span><span class="k">FOR</span><span class="w"> </span><span class="k">SELECT</span><span class="w"> </span><span class="n">LoginName</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&lt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&gt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"></span> +<span class="w"> </span><span class="k">OPEN</span><span class="w"> </span><span class="n">block_cursor</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">block_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> + +<span class="w"> </span><span class="k">WHILE</span><span class="w"> </span><span class="nb">@@FETCH_STATUS</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"></span> +<span class="w"> </span><span class="k">BEGIN</span><span class="w"></span> +<span class="w"> </span><span class="k">exec</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;ALTER LOGIN &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="s1">&#39; DISABLE;&#39;</span><span class="p">);</span><span class="w"></span> + +<span class="w"> </span><span class="k">print</span><span class="w"> </span><span class="s1">&#39;Bloqued usuario &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">block_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> +<span class="w"> </span><span class="k">END</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">CLOSE</span><span class="w"> </span><span class="n">block_cursor</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="k">DEALLOCATE</span><span class="w"> </span><span class="n">block_cursor</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">UPDATE</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">SET</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&lt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&gt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"></span> + + +<span class="w"> </span><span class="cm">/* Libera quem estava bloqueado */</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="nc">CURSOR</span><span class="w"></span> +<span class="w"> </span><span class="k">FOR</span><span class="w"> </span><span class="k">SELECT</span><span class="w"> </span><span class="n">LoginName</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="p">(</span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">OR</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="p">)</span><span class="w"></span> +<span class="w"> </span><span class="k">OPEN</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> + +<span class="w"> </span><span class="k">WHILE</span><span class="w"> </span><span class="nb">@@FETCH_STATUS</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"></span> +<span class="w"> </span><span class="k">BEGIN</span><span class="w"></span> +<span class="w"> </span><span class="k">exec</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;ALTER LOGIN &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"> </span><span class="o">+</span><span class="s1">&#39; ENABLE;&#39;</span><span class="p">);</span><span class="w"></span> + +<span class="w"> </span><span class="k">print</span><span class="w"> </span><span class="s1">&#39;Unbloqued usuario &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> +<span class="w"> </span><span class="k">END</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">CLOSE</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="k">DEALLOCATE</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">UPDATE</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">SET</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="p">(</span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">OR</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="p">)</span><span class="w"></span> +<span class="k">END</span><span class="p">;</span><span class="w"></span> +</code></pre></div> + +<p>Certo, então agora tudo que temos que fazer é definir o job no Agent para rodar a procedure de minuto em minuto. Novamente, a ideia principal é chamar a procedure quando um usuário deve ser bloqueado e quando deve ser desbloqueado.</p> +<div class="highlight"><pre><span></span><code><span class="err"> -- Vai bloquear o usuário protheus das 10 AM até 15 PM</span> +<span class="err"> INSERT INTO dbo.HorariosBloqueio (Id, LoginName, HrInicio, HrTermino) VALUES (NEXT VALUE FOR seq_HorariosBloqueio, &#39;protheus&#39;, &#39;10:00:00&#39;, &#39;15:00:00&#39;);</span> +</code></pre></div>Blocking a user on SQL Server based on a schedule2020-11-14T07:00:00-03:002020-11-14T07:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-11-14:/en/blocking-user-on-sql-server-based-on-schedule.html<p>Ok, some time ago, I've posted about how you can set limits to connections on SQL Server using the <a href="https://www.sipmann.com/limiting-connection-resources-sql-server.html#.X6Cz8IhKhPY">Resource Governor</a>. But what if you can't use it? You always can block logins using a login trigger, but I don't like the idea of having selects running on every login …</p><p>Ok, some time ago, I've posted about how you can set limits to connections on SQL Server using the <a href="https://www.sipmann.com/limiting-connection-resources-sql-server.html#.X6Cz8IhKhPY">Resource Governor</a>. But what if you can't use it? You always can block logins using a login trigger, but I don't like the idea of having selects running on every login. So I came across with a solution using a stored procedure, a table and the Agent.</p> +<p>The main idea is, store the time that a user must be blocked and using the Agent, disable or enable the user. Bellow you can see the table (the table is in Portuguese, but I have a few comment blocks to help you).</p> +<div class="highlight"><pre><span></span><code><span class="k">CREATE</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"> </span><span class="p">(</span><span class="w"></span> +<span class="w"> </span><span class="n">Id</span><span class="w"> </span><span class="nc">INT</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">LoginName</span><span class="w"> </span><span class="nc">NVARCHAR</span><span class="p">(</span><span class="mi">100</span><span class="p">)</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">HrInicio</span><span class="w"> </span><span class="nc">TIME</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"> </span><span class="cm">/* Startint block time */</span><span class="w"></span> +<span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="nc">TIME</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"> </span><span class="cm">/* Ending block time */</span><span class="w"></span> +<span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="nc">INT</span><span class="w"> </span><span class="k">DEFAULT</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="cm">/* 0 = unblocked, 1 = blocked */</span><span class="w"></span> +<span class="w"> </span><span class="k">PRIMARY</span><span class="w"> </span><span class="k">KEY</span><span class="w"> </span><span class="p">(</span><span class="n">Id</span><span class="p">)</span><span class="w"></span> +<span class="p">);</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> + +<span class="cm">/* Don&#39;t block the SA user, precautions, you know */</span><span class="w"></span> +<span class="k">ALTER</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"></span> +<span class="w"> </span><span class="k">ADD</span><span class="w"> </span><span class="k">CONSTRAINT</span><span class="w"> </span><span class="n">chk_users</span><span class="w"> </span><span class="k">CHECK</span><span class="w"> </span><span class="p">(</span><span class="n">LoginName</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;sa&#39;</span><span class="p">));</span><span class="w"></span> + +<span class="k">ALTER</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"></span> +<span class="w"> </span><span class="k">ADD</span><span class="w"> </span><span class="k">CONSTRAINT</span><span class="w"> </span><span class="n">chk_hora_final_maior</span><span class="w"> </span><span class="k">CHECK</span><span class="w"> </span><span class="p">(</span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="n">HrInicio</span><span class="p">);</span><span class="w"></span> + +<span class="k">ALTER</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"></span> +<span class="w"> </span><span class="k">ADD</span><span class="w"> </span><span class="k">CONSTRAINT</span><span class="w"> </span><span class="n">chk_status_bloqueio</span><span class="w"> </span><span class="k">CHECK</span><span class="w"> </span><span class="p">(</span><span class="n">Bloqueado</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">));</span><span class="w"></span> + +<span class="k">CREATE</span><span class="w"> </span><span class="k">SEQUENCE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">seq_HorariosBloqueio</span><span class="w"> </span><span class="k">START</span><span class="w"> </span><span class="k">WITH</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="n">INCREMENT</span><span class="w"> </span><span class="k">BY</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +</code></pre></div> + +<p>After creating the table, let's check the procedure that will handle the enabling/disabling the users. Be aware that on the procedure, I've set the database name where the table was stored, you can change it replacing the <code>DBATOOLS</code> text to the database name where you created the table.</p> +<div class="highlight"><pre><span></span><code><span class="k">IF</span><span class="w"> </span><span class="nf">OBJECT_ID</span><span class="p">(</span><span class="s1">&#39;dbo.sp_ValidarLogin&#39;</span><span class="p">)</span><span class="w"> </span><span class="k">IS</span><span class="w"> </span><span class="k">NULL</span><span class="w"></span> +<span class="w"> </span><span class="k">EXEC</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;CREATE PROCEDURE dbo.sp_ValidarLogin AS RETURN 0;&#39;</span><span class="p">);</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> + +<span class="k">CREATE</span><span class="w"> </span><span class="ow">OR</span><span class="w"> </span><span class="k">ALTER</span><span class="w"> </span><span class="k">PROC</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">sp_ValidarLogin</span><span class="w"></span> +<span class="k">AS</span><span class="w"> </span><span class="k">BEGIN</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="nc">NVARCHAR</span><span class="p">(</span><span class="mi">100</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="nc">TIME</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="k">SET</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nf">CAST</span><span class="p">(</span><span class="nf">GETDATE</span><span class="p">()</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="nc">TIME</span><span class="p">);</span><span class="w"></span> + +<span class="w"> </span><span class="cm">/* Block the ones that aren&#39;t blocked already and maches the time */</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="n">block_cursor</span><span class="w"> </span><span class="nc">CURSOR</span><span class="w"></span> +<span class="w"> </span><span class="k">FOR</span><span class="w"> </span><span class="k">SELECT</span><span class="w"> </span><span class="n">LoginName</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&lt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&gt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"></span> +<span class="w"> </span><span class="k">OPEN</span><span class="w"> </span><span class="n">block_cursor</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">block_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> + +<span class="w"> </span><span class="k">WHILE</span><span class="w"> </span><span class="nb">@@FETCH_STATUS</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"></span> +<span class="w"> </span><span class="k">BEGIN</span><span class="w"></span> +<span class="w"> </span><span class="k">exec</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;ALTER LOGIN &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="s1">&#39; DISABLE;&#39;</span><span class="p">);</span><span class="w"></span> + +<span class="w"> </span><span class="k">print</span><span class="w"> </span><span class="s1">&#39;Bloqued usuario &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">block_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> +<span class="w"> </span><span class="k">END</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">CLOSE</span><span class="w"> </span><span class="n">block_cursor</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="k">DEALLOCATE</span><span class="w"> </span><span class="n">block_cursor</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">UPDATE</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">SET</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&lt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&gt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"></span> + + +<span class="w"> </span><span class="cm">/* Enable up who was blocked */</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="nc">CURSOR</span><span class="w"></span> +<span class="w"> </span><span class="k">FOR</span><span class="w"> </span><span class="k">SELECT</span><span class="w"> </span><span class="n">LoginName</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="p">(</span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">OR</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="p">)</span><span class="w"></span> +<span class="w"> </span><span class="k">OPEN</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> + +<span class="w"> </span><span class="k">WHILE</span><span class="w"> </span><span class="nb">@@FETCH_STATUS</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"></span> +<span class="w"> </span><span class="k">BEGIN</span><span class="w"></span> +<span class="w"> </span><span class="k">exec</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;ALTER LOGIN &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"> </span><span class="o">+</span><span class="s1">&#39; ENABLE;&#39;</span><span class="p">);</span><span class="w"></span> + +<span class="w"> </span><span class="k">print</span><span class="w"> </span><span class="s1">&#39;Unbloqued usuario &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> +<span class="w"> </span><span class="k">END</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">CLOSE</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="k">DEALLOCATE</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">UPDATE</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">SET</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="p">(</span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">OR</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="p">)</span><span class="w"></span> +<span class="k">END</span><span class="p">;</span><span class="w"></span> +</code></pre></div> + +<p>Ok, so now all you have to do, is schedule a job to run that stored procedure from minute to minute. Again, the main idea is tell the procedure when a user must be blocked and when it'll be unblocked. </p> +<div class="highlight"><pre><span></span><code><span class="err"> -- Will block the user protheus from 10 AM till 15 PM</span> +<span class="err"> INSERT INTO dbo.HorariosBloqueio (Id, LoginName, HrInicio, HrTermino) VALUES (NEXT VALUE FOR seq_HorariosBloqueio, &#39;protheus&#39;, &#39;10:00:00&#39;, &#39;15:00:00&#39;);</span> +</code></pre></div>Como definir as colunas no select utilizando Entity Framework2020-10-28T19:00:00-03:002020-10-28T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-28:/pt/select_specific_fields_with_efcore.html<p>Então, você utiliza Entity Framework Core e geralmente faz o seu selecto da seguinte forma, talvez você está retornando muitos dados.</p> +<div class="highlight"><pre><span></span><code><span class="kt">var</span> <span class="n">products</span> <span class="p">=</span> <span class="n">Products</span> + <span class="p">.</span><span class="n">Where</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span> <span class="p">&gt;</span> <span class="m">0</span><span class="p">)</span> + <span class="p">.</span><span class="n">OrderBy</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">)</span> + <span class="p">.</span><span class="n">ToList</span><span class="p">()</span> +</code></pre></div> + +<p>Rodando a query acima, em uma base de testes você obtem o seguinte resultado, veja quantas …</p><p>Então, você utiliza Entity Framework Core e geralmente faz o seu selecto da seguinte forma, talvez você está retornando muitos dados.</p> +<div class="highlight"><pre><span></span><code><span class="kt">var</span> <span class="n">products</span> <span class="p">=</span> <span class="n">Products</span> + <span class="p">.</span><span class="n">Where</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span> <span class="p">&gt;</span> <span class="m">0</span><span class="p">)</span> + <span class="p">.</span><span class="n">OrderBy</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">)</span> + <span class="p">.</span><span class="n">ToList</span><span class="p">()</span> +</code></pre></div> + +<p>Rodando a query acima, em uma base de testes você obtem o seguinte resultado, veja quantas colunas estão retornando da sua base de dados.</p> +<p><img alt="Print com todas as colunas" src="/images/ef_core_allcolumns.png"></p> +<p>No meu caso, eu só pretendo ter de volta as colunas Title, PublishedData e uma pequena descrição. Então para selecionar apenas estes campos, nós temos algumas opções. Na primeira, nós vamos definir os campos e retornar um objeto do tipo Dynamic. A segunda forma, é dar ao .NET o objeto a ser retornado, pode ser por exêmplo um DTO.</p> +<div class="highlight"><pre><span></span><code><span class="kt">var</span> <span class="n">products</span> <span class="p">=</span> <span class="n">Products</span> + + <span class="p">.</span><span class="n">Select</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="k">new</span> <span class="p">{</span><span class="n">p</span><span class="p">.</span><span class="n">ProductID</span><span class="p">,</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">,</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span><span class="p">,</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitPrice</span><span class="p">})</span> + <span class="c1">//.Select(p =&gt; new ProductDTO {p.ProductID, p.ProductName, p.UnitsInStock, p.UnitPrice})</span> + + <span class="p">.</span><span class="n">Where</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span> <span class="p">&gt;</span> <span class="m">0</span><span class="p">)</span> + <span class="p">.</span><span class="n">OrderBy</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">)</span> + <span class="p">.</span><span class="n">ToList</span><span class="p">()</span> +</code></pre></div> + +<p><img alt="Print com menos colunas e também menor quantidade de dados" src="/images/ef_core_less_columns.png"></p>How to set columns on select using Entity Framework2020-10-28T19:00:00-03:002020-10-28T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-28:/en/select_specific_fields_with_efcore.html<p>So, you use Entity Framework Core, and you usually code your selects like the following, maybe you are getting too much data.</p> +<div class="highlight"><pre><span></span><code><span class="kt">var</span> <span class="n">products</span> <span class="p">=</span> <span class="n">Products</span> + <span class="p">.</span><span class="n">Where</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span> <span class="p">&gt;</span> <span class="m">0</span><span class="p">)</span> + <span class="p">.</span><span class="n">OrderBy</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">)</span> + <span class="p">.</span><span class="n">ToList</span><span class="p">()</span> +</code></pre></div> + +<p>Running the query above, on my table, you'll get the following output, take a look …</p><p>So, you use Entity Framework Core, and you usually code your selects like the following, maybe you are getting too much data.</p> +<div class="highlight"><pre><span></span><code><span class="kt">var</span> <span class="n">products</span> <span class="p">=</span> <span class="n">Products</span> + <span class="p">.</span><span class="n">Where</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span> <span class="p">&gt;</span> <span class="m">0</span><span class="p">)</span> + <span class="p">.</span><span class="n">OrderBy</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">)</span> + <span class="p">.</span><span class="n">ToList</span><span class="p">()</span> +</code></pre></div> + +<p>Running the query above, on my table, you'll get the following output, take a look at how many columns you are getting back from your database.</p> +<p><img alt="Screenshot with every single column" src="/images/ef_core_allcolumns.png"></p> +<p>In my case, I only care about the Title, PublishedData, and a small description. So to get back only these fields, we have a few options. In the first one, we'll set the fields and return them as a dynamic object, the second one, is to give the .NET a class to use. </p> +<div class="highlight"><pre><span></span><code><span class="kt">var</span> <span class="n">products</span> <span class="p">=</span> <span class="n">Products</span> + + <span class="p">.</span><span class="n">Select</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="k">new</span> <span class="p">{</span><span class="n">p</span><span class="p">.</span><span class="n">ProductID</span><span class="p">,</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">,</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span><span class="p">,</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitPrice</span><span class="p">})</span> + <span class="c1">//.Select(p =&gt; new ProductDTO {p.ProductID, p.ProductName, p.UnitsInStock, p.UnitPrice})</span> + + <span class="p">.</span><span class="n">Where</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span> <span class="p">&gt;</span> <span class="m">0</span><span class="p">)</span> + <span class="p">.</span><span class="n">OrderBy</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">)</span> + <span class="p">.</span><span class="n">ToList</span><span class="p">()</span> +</code></pre></div> + +<p><img alt="Screenshot with fewer columns and also fewer data size" src="/images/ef_core_less_columns.png"></p>Zabbix Running on Low Memory Mode2020-10-20T19:00:00-03:002020-10-20T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-20:/pt/zabbix-running-on-low-memory-mode.html<p>Olá pessoal! Trago hoje outro post sobre Zabbix. Este é sobre aumentar o cache do seu Zabbix Server. É perfeitamente comum (se você roda com as configurações padrões) receber avisos sobre <code>Zabbix value cache running on low memory mode</code> no seu dashboard ou arquivos de log.</p> +<p><img alt="Zabbix Dashboard alertando sobre problemas de memória" src="/images/zabbix_low_memory_mode.png"> +<img alt="Zabbix Dashboard cache gráfico com 70% utilizado" src="/images/zabbix_cache_filling.png"></p> +<p>Para resolver, abra o …</p><p>Olá pessoal! Trago hoje outro post sobre Zabbix. Este é sobre aumentar o cache do seu Zabbix Server. É perfeitamente comum (se você roda com as configurações padrões) receber avisos sobre <code>Zabbix value cache running on low memory mode</code> no seu dashboard ou arquivos de log.</p> +<p><img alt="Zabbix Dashboard alertando sobre problemas de memória" src="/images/zabbix_low_memory_mode.png"> +<img alt="Zabbix Dashboard cache gráfico com 70% utilizado" src="/images/zabbix_cache_filling.png"></p> +<p>Para resolver, abra o seu arquivo de configuração (<code>zabbix_server.conf</code>) e procure pela tag <em>CacheSize</em>. Descomente a linha e defina um valor maior que 8M (8M é o valor padrão). No meu caso, nós configuramos um cache de 100M. Depois da troca, reinicie o serviço para que o mesmo tome efeito.</p> +<div class="highlight"><pre><span></span><code><span class="c1">### Option: CacheSize</span> +<span class="c1"># Size of configuration cache, in bytes.</span> +<span class="c1"># Shared memory size for storing host, item and trigger data.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 128K-64G</span> +<span class="c1"># Default:</span> +<span class="na">CacheSize</span><span class="o">=</span><span class="s">100M #Descomente esta linha</span> +</code></pre></div> + +<p><img alt="Zabbix Dashboard resolved memory problem" src="/images/zabbix_low_memory_solved.png"></p> +<p>Até breve.</p>Zabbix Running on Low Memory Mode2020-10-20T19:00:00-03:002020-10-20T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-20:/en/zabbix-running-on-low-memory-mode.html<p>Hey folks, another Zabbix post today. This one it's about increasing the Zabbix Server Cache. It's pretty common (if you have the default settings only) get a warning about your <code>Zabbix value cache running on low memory mode</code> at your dashboard or logs.</p> +<p><img alt="Zabbix Dashboard warning about the memory problem" src="/images/zabbix_low_memory_mode.png"> +<img alt="Zabbix Dashboard cache graph 70% used" src="/images/zabbix_cache_filling.png"></p> +<p>To solve, go back to your Zabbix …</p><p>Hey folks, another Zabbix post today. This one it's about increasing the Zabbix Server Cache. It's pretty common (if you have the default settings only) get a warning about your <code>Zabbix value cache running on low memory mode</code> at your dashboard or logs.</p> +<p><img alt="Zabbix Dashboard warning about the memory problem" src="/images/zabbix_low_memory_mode.png"> +<img alt="Zabbix Dashboard cache graph 70% used" src="/images/zabbix_cache_filling.png"></p> +<p>To solve, go back to your Zabbix config file (<code>zabbix_server.conf</code>) and look for the tag <em>CacheSize</em>. Uncomment it and set to a value bigger than 8M (8M it's the default value). In my case, we set a cache of 100M. After the change, restart the service.</p> +<div class="highlight"><pre><span></span><code><span class="c1">### Option: CacheSize</span> +<span class="c1"># Size of configuration cache, in bytes.</span> +<span class="c1"># Shared memory size for storing host, item and trigger data.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 128K-64G</span> +<span class="c1"># Default:</span> +<span class="na">CacheSize</span><span class="o">=</span><span class="s">100M #uncomment this line</span> +</code></pre></div> + +<p><img alt="Zabbix Dashboard resolved memory problem" src="/images/zabbix_low_memory_solved.png"></p> +<p>See ya folks.</p>Monitorando status de replicação do MySQL com PowerShell2020-10-14T19:00:00-03:002020-10-14T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-14:/pt/monitoring-mysql-replication-with-powershell.html<p>Tenho migrado alguns scripts bash que tenho para PowerShell, e chegou a vez de migrar um script de monitoramento de replicação do MySQL. Fica como crédito o script original do <a href="https://handyman.dulare.com/mysql-replication-status-alerts-with-bash-script/">Paweł</a>. É um script bem simples onde eu verifico algumas tags resultantes do <code>SHOW SLAVE STATUS\G</code>, são elas. <code>Slave_IO_Running …</code></p><p>Tenho migrado alguns scripts bash que tenho para PowerShell, e chegou a vez de migrar um script de monitoramento de replicação do MySQL. Fica como crédito o script original do <a href="https://handyman.dulare.com/mysql-replication-status-alerts-with-bash-script/">Paweł</a>. É um script bem simples onde eu verifico algumas tags resultantes do <code>SHOW SLAVE STATUS\G</code>, são elas. <code>Slave_IO_Running</code>, <code>Slave_SQL_Running</code> e <code>Seconds_Behind_Master</code>. Ainda preciso verificar formas mais corretas de armazenar/carregar as variáveis como usuários e senha, se tiver alguma dica, fique à vontade para inclusive fazer um pull request (<a href="https://github.com/sipmann/PowerShellScripts">aqui</a>) no repositório onde vou armazenar alguns dos meus scripts.</p> +<div class="highlight"><pre><span></span><code><span class="cm">&lt;#</span> +<span class="cm"> Variables definition</span> +<span class="cm">#&gt;</span> +<span class="nv">$MaxSeconds</span> <span class="p">=</span> <span class="n">120</span> <span class="c"># Max seconds behind master allowed</span> +<span class="nv">$MysqlUser</span> <span class="p">=</span> <span class="s1">&#39;root&#39;</span> +<span class="nv">$MysqlPass</span> <span class="p">=</span> <span class="s1">&#39;&#39;</span> + +<span class="nv">$MailTo</span> <span class="p">=</span> <span class="s1">&#39;mauricio@sipmann.com&#39;</span> +<span class="nv">$MailFrom</span> <span class="p">=</span> <span class="s1">&#39;mauricio@sipmann.com&#39;</span> + + +<span class="nv">$data</span> <span class="p">=</span> <span class="p">$(</span><span class="n">mysql</span> <span class="n">-u</span> <span class="nv">$MysqlUser</span> <span class="n">-p</span><span class="s2">&quot;$MysqlPass&quot;</span> <span class="n">-e</span> <span class="s1">&#39;SHOW SLAVE STATUS \G&#39;</span><span class="p">)</span> + +<span class="c">#Debug data</span> +<span class="c">#$data = Get-Content &#39;c:\temp\sampleresult.txt&#39;</span> + +<span class="cm">&lt;# Parse the data #&gt;</span> +<span class="nv">$IORunning</span> <span class="p">=</span> <span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Slave_IO_Running:&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> +<span class="nv">$SQLRunning</span> <span class="p">=</span> <span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Slave_SQL_Running:&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> +<span class="nv">$LastErrNo</span> <span class="p">=</span> <span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Last_Errno&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> +<span class="nv">$SecondsBh</span> <span class="p">=</span> <span class="no">[int]</span><span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Seconds_Behind_Master&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> + +<span class="k">If</span> <span class="p">(</span><span class="nv">$IORunning</span> <span class="o">-Eq</span> <span class="s1">&#39;No&#39;</span> <span class="o">-Or</span> <span class="nv">$SQLRunning</span> <span class="o">-Eq</span> <span class="s1">&#39;No&#39;</span> <span class="o">-Or</span> <span class="nv">$SecondsBh</span> <span class="o">-gt</span> <span class="nv">$MaxSeconds</span><span class="p">)</span> <span class="p">{</span> + <span class="nv">$MailBody</span> <span class="p">=</span> <span class="s1">&#39;&lt;h1&gt;Problema na replicação&lt;/h1&gt;&lt;br&gt;&#39;</span> + + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39; IO Running: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$IORunning</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39; SQL Running: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$SQLRunning</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39;Seconds Behind: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$SecondsBh</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39; Last Err No: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$LastErrNo</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + + <span class="cm">&lt;# Send e-mail, maybe some telegram message here too #&gt;</span> + <span class="nb">Send-MailMessage</span> <span class="n">-To</span> <span class="nv">$MailTo</span> <span class="n">-From</span> <span class="nv">$MailFrom</span> <span class="n">-Subject</span> <span class="s1">&#39;Problemas na replicação&#39;</span> <span class="n">-bodyAsHtml</span> <span class="nv">$MailBody</span> <span class="n">-Credential</span> <span class="p">(</span><span class="nb">Get-Credential</span><span class="p">)</span> <span class="n">-SmtpServer</span> <span class="s1">&#39;smtp.office365.com&#39;</span> <span class="n">-Port</span> <span class="n">587</span> <span class="n">-UseSsl</span> +<span class="p">}</span> <span class="k">Else</span> <span class="p">{</span> + <span class="nb">Write-Host</span> <span class="s2">&quot;Up and running&quot;</span> +<span class="p">}</span> +</code></pre></div>Monitoring MySQL Replication Status with PowerShell2020-10-14T19:00:00-03:002020-10-14T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-14:/en/monitoring-mysql-replication-with-powershell.html<p>I've been migration some bash scripts that I have to PowerShell, and it's time to migrate a script that monitors the replication of a MySQL database. The credit for the original script goes to <a href="https://handyman.dulare.com/mysql-replication-status-alerts-with-bash-script/">Paweł</a>. It's a simple script where I seek a few tags/fields that we get from …</p><p>I've been migration some bash scripts that I have to PowerShell, and it's time to migrate a script that monitors the replication of a MySQL database. The credit for the original script goes to <a href="https://handyman.dulare.com/mysql-replication-status-alerts-with-bash-script/">Paweł</a>. It's a simple script where I seek a few tags/fields that we get from <code>SHOW SLAVE STATUS\G</code> command, the fields are. <code>Slave_IO_Running</code>, <code>Slave_SQL_Running</code>, and <code>Seconds_Behind_Master</code>. I still need to figure out the proper way to store/read variables like usernames and passwords, if you have any tips, feel free to even make a pull request (<a href="https://github.com/sipmann/PowerShellScripts">here</a>) at the git where I'll store some scripts.</p> +<div class="highlight"><pre><span></span><code><span class="cm">&lt;#</span> +<span class="cm"> Variables definition</span> +<span class="cm">#&gt;</span> +<span class="nv">$MaxSeconds</span> <span class="p">=</span> <span class="n">120</span> <span class="c"># Max seconds behind master allowed</span> +<span class="nv">$MysqlUser</span> <span class="p">=</span> <span class="s1">&#39;root&#39;</span> +<span class="nv">$MysqlPass</span> <span class="p">=</span> <span class="s1">&#39;&#39;</span> + +<span class="nv">$MailTo</span> <span class="p">=</span> <span class="s1">&#39;mauricio@sipmann.com&#39;</span> +<span class="nv">$MailFrom</span> <span class="p">=</span> <span class="s1">&#39;mauricio@sipmann.com&#39;</span> + + +<span class="nv">$data</span> <span class="p">=</span> <span class="p">$(</span><span class="n">mysql</span> <span class="n">-u</span> <span class="nv">$MysqlUser</span> <span class="n">-p</span><span class="s2">&quot;$MysqlPass&quot;</span> <span class="n">-e</span> <span class="s1">&#39;SHOW SLAVE STATUS \G&#39;</span><span class="p">)</span> + +<span class="c">#Debug data</span> +<span class="c">#$data = Get-Content &#39;c:\temp\sampleresult.txt&#39;</span> + +<span class="cm">&lt;# Parse the data #&gt;</span> +<span class="nv">$IORunning</span> <span class="p">=</span> <span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Slave_IO_Running:&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> +<span class="nv">$SQLRunning</span> <span class="p">=</span> <span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Slave_SQL_Running:&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> +<span class="nv">$LastErrNo</span> <span class="p">=</span> <span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Last_Errno&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> +<span class="nv">$SecondsBh</span> <span class="p">=</span> <span class="no">[int]</span><span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Seconds_Behind_Master&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> + +<span class="k">If</span> <span class="p">(</span><span class="nv">$IORunning</span> <span class="o">-Eq</span> <span class="s1">&#39;No&#39;</span> <span class="o">-Or</span> <span class="nv">$SQLRunning</span> <span class="o">-Eq</span> <span class="s1">&#39;No&#39;</span> <span class="o">-Or</span> <span class="nv">$SecondsBh</span> <span class="o">-gt</span> <span class="nv">$MaxSeconds</span><span class="p">)</span> <span class="p">{</span> + <span class="nv">$MailBody</span> <span class="p">=</span> <span class="s1">&#39;&lt;h1&gt;Problema na replicação&lt;/h1&gt;&lt;br&gt;&#39;</span> + + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39; IO Running: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$IORunning</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39; SQL Running: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$SQLRunning</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39;Seconds Behind: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$SecondsBh</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39; Last Err No: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$LastErrNo</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + + <span class="cm">&lt;# Send e-mail, maybe some telegram message here too #&gt;</span> + <span class="nb">Send-MailMessage</span> <span class="n">-To</span> <span class="nv">$MailTo</span> <span class="n">-From</span> <span class="nv">$MailFrom</span> <span class="n">-Subject</span> <span class="s1">&#39;Problemas na replicação&#39;</span> <span class="n">-bodyAsHtml</span> <span class="nv">$MailBody</span> <span class="n">-Credential</span> <span class="p">(</span><span class="nb">Get-Credential</span><span class="p">)</span> <span class="n">-SmtpServer</span> <span class="s1">&#39;smtp.office365.com&#39;</span> <span class="n">-Port</span> <span class="n">587</span> <span class="n">-UseSsl</span> +<span class="p">}</span> <span class="k">Else</span> <span class="p">{</span> + <span class="nb">Write-Host</span> <span class="s2">&quot;Up and running&quot;</span> +<span class="p">}</span> +</code></pre></div>Microsoft Contra Covid2020-10-03T19:00:00-03:002020-10-03T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-03:/pt/microsoft-against-covid.html<p>Você teve seu trabalho afetado pela pandemia do covid? Bom, na última semana eu postei no <a href="https://grepora.com/2020/09/17/microsoft-ignite-certification-voucher/">Grepora</a> sobre um Voucher para certificação gratuita que a Microsoft estava distribuindo durante o evento Microsoft Ignite. Depois disto, eu fiquei sabendo que eles também estão entregando grandes discontos para quem teve o seu …</p><p>Você teve seu trabalho afetado pela pandemia do covid? Bom, na última semana eu postei no <a href="https://grepora.com/2020/09/17/microsoft-ignite-certification-voucher/">Grepora</a> sobre um Voucher para certificação gratuita que a Microsoft estava distribuindo durante o evento Microsoft Ignite. Depois disto, eu fiquei sabendo que eles também estão entregando grandes discontos para quem teve o seu trabalho afetado pela pandemia do covid. </p> +<p>Para saber se você pode receber este desconto, acesse <a href="https://docs.microsoft.com/en-us/learn/certifications/skillingoffer">https://docs.microsoft.com/en-us/learn/certifications/skillingoffer</a>.</p>Microsoft Against Covid2020-10-03T19:00:00-03:002020-10-03T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-03:/en/microsoft-against-covid.html<p>Has your job been affected by covid? Well, last week I've posted on <a href="https://grepora.com/2020/09/17/microsoft-ignite-certification-voucher/">Grepora</a> about a Free Certification Voucher that Microsoft was giving away at the Microsoft Ignite event. After that, I found that they were also giving a huge discount to people who have had their job affected by …</p><p>Has your job been affected by covid? Well, last week I've posted on <a href="https://grepora.com/2020/09/17/microsoft-ignite-certification-voucher/">Grepora</a> about a Free Certification Voucher that Microsoft was giving away at the Microsoft Ignite event. After that, I found that they were also giving a huge discount to people who have had their job affected by covid pandemic. </p> +<p>To see more details about if you were eligible, access <a href="https://docs.microsoft.com/en-us/learn/certifications/skillingoffer">https://docs.microsoft.com/en-us/learn/certifications/skillingoffer</a>.</p>O poder do PowerShell2020-09-21T19:00:00-03:002020-09-21T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-09-21:/pt/the-power-of-powershell.html<p>Como um usuário linux por muito tempo, eu automatizei algumas tarefas com scripts bash e fiquei longe do PowerShell... Voltei a utilizar Windows alguns anos atrás e ainda assim, não dei uma chance ao PS. Mas porque não? Eu fiz alguns scripts para automatizar algumas tarefas em um servidor Protheus …</p><p>Como um usuário linux por muito tempo, eu automatizei algumas tarefas com scripts bash e fiquei longe do PowerShell... Voltei a utilizar Windows alguns anos atrás e ainda assim, não dei uma chance ao PS. Mas porque não? Eu fiz alguns scripts para automatizar algumas tarefas em um servidor Protheus.</p> +<p>Eu acabei achando os scripts PS de fácil leitura e entendimento. Abaixo, nós temos um script para remover arquivos filtrando pela sua extensão (ou sem extensão alguma no caso do script em questão).</p> +<div class="highlight"><pre><span></span><code><span class="nb">Get-ChildItem</span> <span class="s2">&quot;C:\TOTVS\protheus_data\system&quot;</span> <span class="o">-File</span> <span class="n">-Filter</span> <span class="p">*.</span> <span class="p">|</span> <span class="nb">Move-Item</span> <span class="n">-Force</span> <span class="n">-Destination</span> <span class="p">{</span> + <span class="cm">&lt;# Diretório ao qual os arquivos vão ser movidos. Você pode utilizar formatos de data para nomear os diretórios #&gt;</span> + <span class="cm">&lt;# LastWriteTime é a propriedade do arquivo corrent #&gt;</span> + <span class="nv">$dir</span> <span class="p">=</span> <span class="s2">&quot;C:\bad_files\{0:yyyy\\MM\\dd}&quot;</span> <span class="o">-f</span> <span class="nv">$_</span><span class="p">.</span><span class="n">LastWriteTime</span> + <span class="nv">$null</span> <span class="p">=</span> <span class="n">mkdir</span> <span class="nv">$dir</span> <span class="n">-Force</span> + <span class="s2">&quot;$dir\</span><span class="p">$(</span><span class="nv">$_</span><span class="p">.</span><span class="n">Name</span><span class="p">)</span><span class="s2">&quot;</span> +<span class="p">}</span> +</code></pre></div> + +<p>Você já precisou remover arquivos baseado no conteúdo de outro arquivo? Abaixo um script onde eu leio um arquivo que contem os nomes de arquivos que eu desejo remover. </p> +<div class="highlight"><pre><span></span><code><span class="k">foreach</span><span class="p">(</span><span class="nv">$line</span> <span class="k">in</span> <span class="nb">Get-Content</span> <span class="p">.\</span><span class="n">Desktop</span><span class="p">\</span><span class="n">bad_files</span><span class="p">.</span><span class="n">txt</span><span class="p">)</span> <span class="p">{</span> + <span class="k">if</span> <span class="p">(</span><span class="nb">Test-Path</span><span class="p">(</span><span class="s1">&#39;\\x.y.z.a\c$\TOTVS\protheus_data\xmls\&#39;</span><span class="p">+</span><span class="nv">$line</span><span class="p">+</span><span class="s1">&#39;.xml&#39;</span><span class="p">))</span> <span class="p">{</span> + <span class="nb">Remove-Item</span><span class="p">(</span><span class="s1">&#39;\\x.y.z.a\c$\TOTVS\protheus_data\xmls\&#39;</span><span class="p">+</span><span class="nv">$line</span><span class="p">+</span><span class="s1">&#39;.xml&#39;</span><span class="p">)</span> + <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> + <span class="nb">echo </span><span class="nv">$line</span> <span class="p">+</span> <span class="s1">&#39; - File not found&#39;</span> + <span class="p">}</span> +<span class="p">}</span> +</code></pre></div> + +<p>E um script bonus para parar e iniciar serviços (se você gerencia um servidor Protheus, você sabe o porque eu faço isto).</p> +<div class="highlight"><pre><span></span><code><span class="nv">$servicesNames</span> <span class="p">=</span> <span class="s1">&#39;app_main&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker1&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker2&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker3&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker4&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker5&#39;</span> + +<span class="nb">Write-host</span> <span class="s2">&quot;Parando Serviços&quot;</span> +<span class="nb">Write-host</span> <span class="s2">&quot;--------------------------&quot;</span> + +<span class="k">foreach</span> <span class="p">(</span><span class="nv">$srv</span> <span class="k">in</span> <span class="nv">$servicesNames</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Write-host</span> <span class="s2">&quot;Parando: &quot;</span> <span class="p">+</span> <span class="nv">$srv</span> + <span class="nv">$SrvPID</span> <span class="p">=</span> <span class="p">(</span><span class="nb">get-wmiobject</span> <span class="n">win32_service</span> <span class="p">|</span> <span class="nb">where </span><span class="p">{</span> <span class="nv">$_</span><span class="p">.</span><span class="n">name</span> <span class="o">-eq</span> <span class="nv">$srv</span><span class="p">}).</span><span class="n">processID</span> + <span class="nb">Write-host</span> <span class="s2">&quot;PID: &quot;</span> <span class="p">+</span> <span class="nv">$SrvPID</span> + + <span class="cm">&lt;# Força a parada caso o serviço esteja travado #&gt;</span> + <span class="nb">Stop-Process</span> <span class="nv">$ServicePID</span> <span class="n">-Force</span> + <span class="nb">Write-host</span> <span class="s2">&quot;PDI &quot;</span> <span class="p">+</span> <span class="nv">$SrvPID</span> <span class="p">+</span> <span class="s2">&quot; parado&quot;</span> +<span class="p">}</span> + + +<span class="nb">Write-host</span> <span class="s2">&quot;Inicializando Serviços&quot;</span> +<span class="nb">Write-host</span> <span class="s2">&quot;--------------------------&quot;</span> + +<span class="k">foreach</span> <span class="p">(</span><span class="nv">$srv</span> <span class="k">in</span> <span class="nv">$servicesNames</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Write-host</span> <span class="s2">&quot;Inicializando: &quot;</span> <span class="p">+</span> <span class="nv">$srv</span> + <span class="nb">Start-Service</span> <span class="nv">$srv</span> +<span class="p">}</span> +</code></pre></div> + +<p>Você tem algum script de automação? Compartilhe conosco :)</p>The power of PowerShell2020-09-21T19:00:00-03:002020-09-21T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-09-21:/en/the-power-of-powershell.html<p>As a long time Linux user, I've automated a few things with bash scripts and stayed away from PowerShell... I've moved to a Windows environment a few years ago and still, haven gave a shot to PS. But why not? I've made a few scripts to automate some tasks at …</p><p>As a long time Linux user, I've automated a few things with bash scripts and stayed away from PowerShell... I've moved to a Windows environment a few years ago and still, haven gave a shot to PS. But why not? I've made a few scripts to automate some tasks at a Protheus server.</p> +<p>I found the PS scripts being easy to read and understand. Bellow, we have a script to remove files filtering their extension (or no extension at all like the following script). </p> +<div class="highlight"><pre><span></span><code><span class="nb">Get-ChildItem</span> <span class="s2">&quot;C:\TOTVS\protheus_data\system&quot;</span> <span class="o">-File</span> <span class="n">-Filter</span> <span class="p">*.</span> <span class="p">|</span> <span class="nb">Move-Item</span> <span class="n">-Force</span> <span class="n">-Destination</span> <span class="p">{</span> + <span class="cm">&lt;# Diretory where the files will be moved. You can use Date formats to help name it #&gt;</span> + <span class="cm">&lt;# LastWriteTime proprtie from the current file #&gt;</span> + <span class="nv">$dir</span> <span class="p">=</span> <span class="s2">&quot;C:\bad_files\{0:yyyy\\MM\\dd}&quot;</span> <span class="o">-f</span> <span class="nv">$_</span><span class="p">.</span><span class="n">LastWriteTime</span> + <span class="nv">$null</span> <span class="p">=</span> <span class="n">mkdir</span> <span class="nv">$dir</span> <span class="n">-Force</span> + <span class="s2">&quot;$dir\</span><span class="p">$(</span><span class="nv">$_</span><span class="p">.</span><span class="n">Name</span><span class="p">)</span><span class="s2">&quot;</span> +<span class="p">}</span> +</code></pre></div> + +<p>Have you ever been in the need to remove files based on other file content? Bello a script where I read a file that has the names of files that I want to remove. </p> +<div class="highlight"><pre><span></span><code><span class="k">foreach</span><span class="p">(</span><span class="nv">$line</span> <span class="k">in</span> <span class="nb">Get-Content</span> <span class="p">.\</span><span class="n">Desktop</span><span class="p">\</span><span class="n">bad_files</span><span class="p">.</span><span class="n">txt</span><span class="p">)</span> <span class="p">{</span> + <span class="k">if</span> <span class="p">(</span><span class="nb">Test-Path</span><span class="p">(</span><span class="s1">&#39;\\x.y.z.a\c$\TOTVS\protheus_data\xmls\&#39;</span><span class="p">+</span><span class="nv">$line</span><span class="p">+</span><span class="s1">&#39;.xml&#39;</span><span class="p">))</span> <span class="p">{</span> + <span class="nb">Remove-Item</span><span class="p">(</span><span class="s1">&#39;\\x.y.z.a\c$\TOTVS\protheus_data\xmls\&#39;</span><span class="p">+</span><span class="nv">$line</span><span class="p">+</span><span class="s1">&#39;.xml&#39;</span><span class="p">)</span> + <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> + <span class="nb">echo </span><span class="nv">$line</span> <span class="p">+</span> <span class="s1">&#39; - File not found&#39;</span> + <span class="p">}</span> +<span class="p">}</span> +</code></pre></div> + +<p>And a bonus script to stop/start services (if you handle some Protheus Server, you know why I do that).</p> +<div class="highlight"><pre><span></span><code><span class="nv">$servicesNames</span> <span class="p">=</span> <span class="s1">&#39;app_main&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker1&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker2&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker3&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker4&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker5&#39;</span> + +<span class="nb">Write-host</span> <span class="s2">&quot;Stoping Services&quot;</span> +<span class="nb">Write-host</span> <span class="s2">&quot;--------------------------&quot;</span> + +<span class="k">foreach</span> <span class="p">(</span><span class="nv">$srv</span> <span class="k">in</span> <span class="nv">$servicesNames</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Write-host</span> <span class="s2">&quot;Stopping: &quot;</span> <span class="p">+</span> <span class="nv">$srv</span> + <span class="nv">$SrvPID</span> <span class="p">=</span> <span class="p">(</span><span class="nb">get-wmiobject</span> <span class="n">win32_service</span> <span class="p">|</span> <span class="nb">where </span><span class="p">{</span> <span class="nv">$_</span><span class="p">.</span><span class="n">name</span> <span class="o">-eq</span> <span class="nv">$srv</span><span class="p">}).</span><span class="n">processID</span> + <span class="nb">Write-host</span> <span class="s2">&quot;PID: &quot;</span> <span class="p">+</span> <span class="nv">$SrvPID</span> + + <span class="cm">&lt;# Force if the proccess is stucked #&gt;</span> + <span class="nb">Stop-Process</span> <span class="nv">$SrvPID</span> <span class="n">-Force</span> + <span class="nb">Write-host</span> <span class="s2">&quot;PDI &quot;</span> <span class="p">+</span> <span class="nv">$SrvPID</span> <span class="p">+</span> <span class="s2">&quot; stopped&quot;</span> +<span class="p">}</span> + + +<span class="nb">Write-host</span> <span class="s2">&quot;Starting Services&quot;</span> +<span class="nb">Write-host</span> <span class="s2">&quot;--------------------------&quot;</span> + +<span class="k">foreach</span> <span class="p">(</span><span class="nv">$srv</span> <span class="k">in</span> <span class="nv">$servicesNames</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Write-host</span> <span class="s2">&quot;Starting: &quot;</span> <span class="p">+</span> <span class="nv">$srv</span> + <span class="nb">Start-Service</span> <span class="nv">$srv</span> +<span class="p">}</span> +</code></pre></div> + +<p>Do you have any automated script? Share with us :)</p>Top Level Statement no C# 92020-07-29T19:00:00-03:002020-07-29T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-07-29:/pt/top_level_statement_csharp_9.html<p>Olá pessoal, venho hoje falar sobre uma novidade que estará disponível na versão 9 do C#. Toda vez que você deseja criar um novo projeto, você sempre tem o mesmo arquivo Main, com a mesma estrutura. Na próxima versão do C# (versão 9), nós teremos uma nova funcionalidade chamada <code>Top …</code></p><p>Olá pessoal, venho hoje falar sobre uma novidade que estará disponível na versão 9 do C#. Toda vez que você deseja criar um novo projeto, você sempre tem o mesmo arquivo Main, com a mesma estrutura. Na próxima versão do C# (versão 9), nós teremos uma nova funcionalidade chamada <code>Top Level Statement</code>. Com isto, poderemos programar a nossa aplicação sem toda aquela estrutura de <code>namespace/class/public void static main</code>. Veja o código abaixo.</p> +<div class="highlight"><pre><span></span><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span> + +<span class="n">Console</span><span class="p">.</span><span class="n">WriteLine</span><span class="p">(</span><span class="s">&quot;Hello World!&quot;</span><span class="p">);</span> +</code></pre></div> + +<p>Parece muito simples, não é? Com isto, você pode brincar com seu código e até mesmo programar uma pequena WEB API. Para começar a brincar com estas novas <em>features</em>, primeiramente faça o download do preview do <a href="https://dotnet.microsoft.com/download/dotnet/5.0">.net 5 SDK</a> e modifique o seu arquivo <code>.csproj</code> para apontar o framework para <code>.net5.0</code> e a versão de preview da linguagem. Abaixo como uma aplicação de console deve ficar.</p> +<div class="highlight"><pre><span></span><code><span class="nt">&lt;Project</span> <span class="na">Sdk=</span><span class="s">&quot;Microsoft.NET.Sdk&quot;</span><span class="nt">&gt;</span> + <span class="nt">&lt;PropertyGroup&gt;</span> + <span class="nt">&lt;OutputType&gt;</span>Exe<span class="nt">&lt;/OutputType&gt;</span> + <span class="nt">&lt;TargetFramework&gt;</span>net5.0<span class="nt">&lt;/TargetFramework&gt;</span> + <span class="nt">&lt;LangVersion&gt;</span>preview<span class="nt">&lt;/LangVersion&gt;</span> + <span class="nt">&lt;/PropertyGroup&gt;</span> +<span class="nt">&lt;/Project&gt;</span> +</code></pre></div> + +<p>E assim você está pronto para brincar com as novas funcionalidades que estão disponíveis na versão preview. Vamos programar uma aplicação simples que faz uma requisição na API da NASA e printe a Imagem do Dia no console. Não é nenhum código mirabolante, é simplesmente para exemplificar o quão simples uma simples chamada de API pode ser. Feito isto, porque não salvar a imagem como um arquivo? Ou então enviar essa imagem via telegram?</p> +<div class="highlight"><pre><span></span><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Net.Http</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Text.Json</span><span class="p">;</span> + +<span class="kt">var</span> <span class="n">API</span> <span class="p">=</span> <span class="s">&quot;https://api.nasa.gov/planetary/apod?hd=true&amp;api_key=DEMO_KEY&quot;</span><span class="p">;</span> +<span class="kt">var</span> <span class="n">cli</span> <span class="p">=</span> <span class="k">new</span> <span class="n">HttpClient</span><span class="p">();</span> + +<span class="kt">var</span> <span class="n">response</span> <span class="p">=</span> <span class="k">await</span> <span class="n">cli</span><span class="p">.</span><span class="n">GetAsync</span><span class="p">(</span><span class="n">API</span><span class="p">);</span> +<span class="kt">var</span> <span class="n">data</span> <span class="p">=</span> <span class="n">JsonSerializer</span><span class="p">.</span><span class="n">Deserialize</span><span class="p">&lt;</span><span class="n">NasaApi</span><span class="p">&gt;(</span><span class="k">await</span> <span class="n">response</span><span class="p">.</span><span class="n">Content</span><span class="p">.</span><span class="n">ReadAsStringAsync</span><span class="p">());</span> + +<span class="n">Console</span><span class="p">.</span><span class="n">WriteLine</span><span class="p">(</span><span class="n">data</span><span class="p">.</span><span class="n">Url</span><span class="p">);</span> +</code></pre></div> + +<p>Por hoje é isso. Fique de olho nas novas features que o C# 9 vai nos trazer. Já temos várias disponíveis hoje para testar, esta é apenas uma delas.</p>Top Level Statement in C# 92020-07-29T19:00:00-03:002020-07-29T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-07-29:/en/top_level_statement_csharp_9.html<p>Hey folks, I'm coming along to tell you a few things about the new feature of C# 9. Every time you want to start a new project, you always have the same Main File, with the same structure. At the next version of C# (version 9), we'll have a new …</p><p>Hey folks, I'm coming along to tell you a few things about the new feature of C# 9. Every time you want to start a new project, you always have the same Main File, with the same structure. At the next version of C# (version 9), we'll have a new feature called <code>Top Level Statement</code>. With that, we'll be able to code our app without any namespace/class/public void static main structure. Take a look at the code below.</p> +<div class="highlight"><pre><span></span><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span> + +<span class="n">Console</span><span class="p">.</span><span class="n">WriteLine</span><span class="p">(</span><span class="s">&quot;Hello World!&quot;</span><span class="p">);</span> +</code></pre></div> + +<p>It looks pretty simple, but with this, you can play around with your code, and even code a simple/tiny Web API. To start playing with the new features, firstly download the <a href="https://dotnet.microsoft.com/download/dotnet/5.0">.net 5 SDK</a> and change your <code>.csproj</code> file to target the .net 5 and language preview like bellow.</p> +<div class="highlight"><pre><span></span><code><span class="nt">&lt;Project</span> <span class="na">Sdk=</span><span class="s">&quot;Microsoft.NET.Sdk&quot;</span><span class="nt">&gt;</span> + <span class="nt">&lt;PropertyGroup&gt;</span> + <span class="nt">&lt;OutputType&gt;</span>Exe<span class="nt">&lt;/OutputType&gt;</span> + <span class="nt">&lt;TargetFramework&gt;</span>net5.0<span class="nt">&lt;/TargetFramework&gt;</span> + <span class="nt">&lt;LangVersion&gt;</span>preview<span class="nt">&lt;/LangVersion&gt;</span> + <span class="nt">&lt;/PropertyGroup&gt;</span> +<span class="nt">&lt;/Project&gt;</span> +</code></pre></div> + +<p>And you're ready to play with the awesome features available in the preview. Let's code a way to get the image of the day from NASA API and print the Picture of the Day. No awesome code here, it's really a way to show how simple a simple call could be. After here, why not save the image in a file? Maybe send the file over telegram?</p> +<div class="highlight"><pre><span></span><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Net.Http</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Text.Json</span><span class="p">;</span> + +<span class="kt">var</span> <span class="n">API</span> <span class="p">=</span> <span class="s">&quot;https://api.nasa.gov/planetary/apod?hd=true&amp;api_key=DEMO_KEY&quot;</span><span class="p">;</span> +<span class="kt">var</span> <span class="n">cli</span> <span class="p">=</span> <span class="k">new</span> <span class="n">HttpClient</span><span class="p">();</span> + +<span class="kt">var</span> <span class="n">response</span> <span class="p">=</span> <span class="k">await</span> <span class="n">cli</span><span class="p">.</span><span class="n">GetAsync</span><span class="p">(</span><span class="n">API</span><span class="p">);</span> +<span class="kt">var</span> <span class="n">data</span> <span class="p">=</span> <span class="n">JsonSerializer</span><span class="p">.</span><span class="n">Deserialize</span><span class="p">&lt;</span><span class="n">NasaApi</span><span class="p">&gt;(</span><span class="k">await</span> <span class="n">response</span><span class="p">.</span><span class="n">Content</span><span class="p">.</span><span class="n">ReadAsStringAsync</span><span class="p">());</span> + +<span class="n">Console</span><span class="p">.</span><span class="n">WriteLine</span><span class="p">(</span><span class="n">data</span><span class="p">.</span><span class="n">Url</span><span class="p">);</span> +</code></pre></div> + +<p>That's it for today folks. Keep an eye open for the awesome features C# 9 will bring to us, there's plenty more features already available.</p>Zabbix poller processes more than 75%2020-07-02T19:00:00-03:002020-07-02T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-07-02:/pt/zabbix-poller-processes-more-than-75.html<p>Este é o terceiro post sobre configurações para o Zabbix. Todas as alterações que eu sugiro nestes posts, são baseadas em um servidor com 50+ hosts. Outro problema que pode ocorrer em seu servidor, é o poller de informações ficar sobrecarregado pela quantidade de servidores que ele precisa pegar carga …</p><p>Este é o terceiro post sobre configurações para o Zabbix. Todas as alterações que eu sugiro nestes posts, são baseadas em um servidor com 50+ hosts. Outro problema que pode ocorrer em seu servidor, é o poller de informações ficar sobrecarregado pela quantidade de servidores que ele precisa pegar carga de informações juntamente com os servidores que não respondem a requisição. Abaixo duas imagens onde você pode ver o log e um gráfico onde aparecem os percentuais de uso dos poller. </p> +<p><img alt="Dashboard log sobre o processo do poller" src="/images/zabbix_pooler.png"></p> +<p><img alt="Gráfico mostrando o percentual de utilização de cada coletor" src="/images/zabbix_pooler_3.png"></p> +<p>Para resolver o problema acima, vamos voltar ao arquivo de configuração <code>zabbix_server.conf</code> e localizar duas variáveis, <code>StartPollers</code> e <code>StartPollersUnreachable</code>. Aumente o valor delas conforme necessário. Não existe um número mágico, você deve verificar o que melhor funciona para você. Mas tenha em mente que <code>StartPollersUnreachable</code> é responsável por aqueles hosts que não respondem ou não são localizados e irão segurar a thread do poller por mais tempo, causando uma fila e um maior processamento/tempo de atualização.</p> +<div class="highlight"><pre><span></span><code><span class="c1">### Option: StartPollers</span> +<span class="c1"># Number of pre-forked instances of pollers.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 0-1000</span> +<span class="c1"># Default:</span> +<span class="na">StartPollers</span><span class="o">=</span><span class="s">20</span> + +<span class="c1">#...</span> + +<span class="c1">### Option: StartPollersUnreachable</span> +<span class="c1"># Number of pre-forked instances of pollers for unreachable hosts (including IPMI and Java).</span> +<span class="c1"># At least one poller for unreachable hosts must be running if regular, IPMI or Java pollers</span> +<span class="c1"># are started.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 0-1000</span> +<span class="c1"># Default:</span> +<span class="na">StartPollersUnreachable</span><span class="o">=</span><span class="s">5</span> +</code></pre></div> + +<p>Depois da alteração, reinicie o serviço e espere alguns momentos e veja o seu dashboard novamente. Abaixo o efeito que a troca teve em um dos servidores que acompanho.</p> +<p><img alt="Gráfico mostrando os novos percentuais de utilização dos processos após as alterações" src="/images/zabbix_pooler_4.png"></p>Zabbix poller processes more than 75%2020-07-02T19:00:00-03:002020-07-02T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-07-02:/en/zabbix-poller-processes-more-than-75.html<p>Hey folks, this is the third post about tweaking the Zabbix configurations. All changes that I've suggested here were based on a Zabbix Server with 50+ hosts. Another thing that can happen to your server, it's the poller get overwhelmed by the amount of servers that need to be polled …</p><p>Hey folks, this is the third post about tweaking the Zabbix configurations. All changes that I've suggested here were based on a Zabbix Server with 50+ hosts. Another thing that can happen to your server, it's the poller get overwhelmed by the amount of servers that need to be polled plus the ones that are not responding. Bellow two images where you can see the log and the graphic where you can see the usage percent. </p> +<p><img alt="Dashboard log about the poller processes" src="/images/zabbix_pooler.png"></p> +<p><img alt="Graph showing the utilization percent of each collector" src="/images/zabbix_pooler_3.png"></p> +<p>To solve, let's go back to the <code>zabbix_server.conf</code> file and find two variables, <code>StartPollers</code> and <code>StartPollersUnreachable</code>. Increase them as needed. There's no magic number, you must see what works for you. But keep in mind that the <code>StartPollersUnreachable</code> is responsible for that host that can't be "reached" (of course) and will hold your poller more time.</p> +<div class="highlight"><pre><span></span><code><span class="c1">### Option: StartPollers</span> +<span class="c1"># Number of pre-forked instances of pollers.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 0-1000</span> +<span class="c1"># Default:</span> +<span class="na">StartPollers</span><span class="o">=</span><span class="s">20</span> + +<span class="c1">#...</span> + +<span class="c1">### Option: StartPollersUnreachable</span> +<span class="c1"># Number of pre-forked instances of pollers for unreachable hosts (including IPMI and Java).</span> +<span class="c1"># At least one poller for unreachable hosts must be running if regular, IPMI or Java pollers</span> +<span class="c1"># are started.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 0-1000</span> +<span class="c1"># Default:</span> +<span class="na">StartPollersUnreachable</span><span class="o">=</span><span class="s">5</span> +</code></pre></div> + +<p>After the change, restart the server and wait a few moments and take a look again at your dashboard. Bellow the effect that I've got.</p> +<p><img alt="Graph showing the new utilization percent of the processes after the changes" src="/images/zabbix_pooler_4.png"></p>Monitorando a disponibilidade de um Website com Azure Functions2020-06-22T19:00:00-03:002020-06-22T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-06-22:/pt/monitoring-website-heath-with-azure-functions.html<p>Algumas vezes você se depara com a necessidade de monitorar a disponibilidade de um website ou mudanças em seu conteúdo. É claro que temos diversas opções disponíveis no mercado, mas para fins de curiosidade, vamos programar o nosso próprio e ver o que podemos fazer. Primeiramente, tudo que você ver …</p><p>Algumas vezes você se depara com a necessidade de monitorar a disponibilidade de um website ou mudanças em seu conteúdo. É claro que temos diversas opções disponíveis no mercado, mas para fins de curiosidade, vamos programar o nosso próprio e ver o que podemos fazer. Primeiramente, tudo que você ver aqui, você pode utilizar o <a href="https://azure.microsoft.com/free/">tier gratuito</a> da Azure.</p> +<p>A ideia principal da nossa aplicação vai ser monitorar a disponibilidade do website (status code). Para criar um projeto de Azure Function, siga os passos abaixo.</p> +<p><img alt="Passos para criar um projeto Azure Functions" src="/images/azure_functions.gif"></p> +<p>Depois de criar o projeto, você vai ter alguns arquivos. Abra o arquivo principal (<code>HttpCheck.cs</code> no meu caso) e começe a programar. O arquivo principal terá uma função chamada <code>Run</code> e você pode progamar nela o seu request. Eu criei um método <code>async</code> para fazer as requisições e printar a saída diretamente no console. O código completo pode ser visto abaixo.</p> +<div class="highlight"><pre><span></span><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Linq</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Net.Http</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Threading.Tasks</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">Microsoft.Azure.WebJobs</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">Microsoft.Azure.WebJobs.Host</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">Microsoft.Extensions.Logging</span><span class="p">;</span> + +<span class="k">namespace</span> <span class="nn">Sipmann.CheckMySite</span> +<span class="p">{</span> + <span class="k">public</span> <span class="k">static</span> <span class="k">class</span> <span class="nc">HttpCheck</span> + <span class="p">{</span> + + <span class="k">private</span> <span class="k">static</span> <span class="k">async</span> <span class="n">Task</span> <span class="nf">GetTask</span><span class="p">(</span><span class="kt">string</span> <span class="n">url</span><span class="p">,</span> <span class="n">ILogger</span> <span class="n">log</span><span class="p">)</span> + <span class="p">{</span> + <span class="kt">var</span> <span class="n">request</span> <span class="p">=</span> <span class="k">new</span> <span class="n">HttpRequestMessage</span><span class="p">(</span><span class="n">HttpMethod</span><span class="p">.</span><span class="n">Get</span><span class="p">,</span> <span class="n">url</span><span class="p">);</span> + + <span class="kt">var</span> <span class="n">client</span> <span class="p">=</span> <span class="k">new</span> <span class="n">HttpClient</span><span class="p">();</span> + <span class="kt">var</span> <span class="n">response</span> <span class="p">=</span> <span class="k">await</span> <span class="n">client</span><span class="p">.</span><span class="n">SendAsync</span><span class="p">(</span><span class="n">request</span><span class="p">);</span> + + <span class="k">if</span> <span class="p">(</span><span class="n">response</span><span class="p">.</span><span class="n">IsSuccessStatusCode</span><span class="p">)</span> + <span class="p">{</span> + <span class="n">log</span><span class="p">.</span><span class="n">LogInformation</span><span class="p">(</span><span class="err">$</span><span class="s">&quot;URL ${url} esta OK&quot;</span><span class="p">);</span> + <span class="p">}</span> + <span class="k">else</span> + <span class="p">{</span> + <span class="n">log</span><span class="p">.</span><span class="n">LogInformation</span><span class="p">(</span><span class="err">$</span><span class="s">&quot;URL ${url} não esta OK&quot;</span><span class="p">);</span> + <span class="p">}</span> + <span class="p">}</span> + +<span class="na"> [FunctionName(&quot;HttpCheck&quot;)]</span> + <span class="k">public</span> <span class="k">static</span> <span class="k">void</span> <span class="nf">Run</span><span class="p">([</span><span class="n">TimerTrigger</span><span class="p">(</span><span class="s">&quot;0 */5 * * * *&quot;</span><span class="p">)]</span><span class="n">TimerInfo</span> <span class="n">myTimer</span><span class="p">,</span> <span class="n">ILogger</span> <span class="n">log</span><span class="p">)</span> + <span class="p">{</span> + <span class="c1">// URL a verificar a saúde</span> + <span class="kt">var</span> <span class="n">urls</span> <span class="p">=</span> <span class="k">new</span><span class="p">[]{</span><span class="s">&quot;https://www.sipmann.com&quot;</span><span class="p">,</span> <span class="s">&quot;https://www.canezecanez.com.br&quot;</span><span class="p">};</span> + + <span class="c1">// Starta cada request e aguarda todos de uma vez só</span> + <span class="n">Task</span><span class="p">.</span><span class="n">WaitAll</span><span class="p">(</span><span class="n">urls</span><span class="p">.</span><span class="n">Select</span><span class="p">(</span><span class="n">url</span> <span class="p">=&gt;</span> <span class="n">GetTask</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">log</span><span class="p">)).</span><span class="n">ToArray</span><span class="p">());</span> + <span class="n">log</span><span class="p">.</span><span class="n">LogInformation</span><span class="p">(</span><span class="err">$</span><span class="s">&quot;Finalizou a fila&quot;</span><span class="p">);</span> + <span class="p">}</span> + <span class="p">}</span> +<span class="p">}</span> +</code></pre></div> + +<p>Agora você pode melhorar a função e talvez enviar alguns alertas. Como por exêmplo mensagens no Telegram quando um dos sites ficar off (status code 404).</p>Monitoring a Website heath with Azure Functions2020-06-22T19:00:00-03:002020-06-22T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-06-22:/en/monitoring-website-heath-with-azure-functions.html<p>Sometimes you get your self in need to monitor a website's health or it's content for changes. Of course, there's plenty of options out there, but for the sake of curiosity, let's code our own to see what we can do. First things first. Everything you'll see here, you can …</p><p>Sometimes you get your self in need to monitor a website's health or it's content for changes. Of course, there's plenty of options out there, but for the sake of curiosity, let's code our own to see what we can do. First things first. Everything you'll see here, you can achieve with the <a href="https://azure.microsoft.com/free/">free tier</a> of azure.</p> +<p>The main idea of our app will be to monitor website health (status code). To create a new Azure Function Project, follow the steps below.</p> +<p><img alt="Steps to create a azure function project" src="/images/azure_functions.gif"></p> +<p>After creating the project, you'll have a few files. Open your main file and start coding. The main file will have a function called <code>Run</code> and you can code your request method. I've created an <code>async</code> method to make the request and log the output at the console. The full code you can see below.</p> +<div class="highlight"><pre><span></span><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Linq</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Net.Http</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Threading.Tasks</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">Microsoft.Azure.WebJobs</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">Microsoft.Azure.WebJobs.Host</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">Microsoft.Extensions.Logging</span><span class="p">;</span> + +<span class="k">namespace</span> <span class="nn">Sipmann.CheckMySite</span> +<span class="p">{</span> + <span class="k">public</span> <span class="k">static</span> <span class="k">class</span> <span class="nc">HttpCheck</span> + <span class="p">{</span> + + <span class="k">private</span> <span class="k">static</span> <span class="k">async</span> <span class="n">Task</span> <span class="nf">GetTask</span><span class="p">(</span><span class="kt">string</span> <span class="n">url</span><span class="p">,</span> <span class="n">ILogger</span> <span class="n">log</span><span class="p">)</span> + <span class="p">{</span> + <span class="kt">var</span> <span class="n">request</span> <span class="p">=</span> <span class="k">new</span> <span class="n">HttpRequestMessage</span><span class="p">(</span><span class="n">HttpMethod</span><span class="p">.</span><span class="n">Get</span><span class="p">,</span> <span class="n">url</span><span class="p">);</span> + + <span class="kt">var</span> <span class="n">client</span> <span class="p">=</span> <span class="k">new</span> <span class="n">HttpClient</span><span class="p">();</span> + <span class="kt">var</span> <span class="n">response</span> <span class="p">=</span> <span class="k">await</span> <span class="n">client</span><span class="p">.</span><span class="n">SendAsync</span><span class="p">(</span><span class="n">request</span><span class="p">);</span> + + <span class="k">if</span> <span class="p">(</span><span class="n">response</span><span class="p">.</span><span class="n">IsSuccessStatusCode</span><span class="p">)</span> + <span class="p">{</span> + <span class="n">log</span><span class="p">.</span><span class="n">LogInformation</span><span class="p">(</span><span class="err">$</span><span class="s">&quot;URL ${url} esta OK&quot;</span><span class="p">);</span> + <span class="p">}</span> + <span class="k">else</span> + <span class="p">{</span> + <span class="n">log</span><span class="p">.</span><span class="n">LogInformation</span><span class="p">(</span><span class="err">$</span><span class="s">&quot;URL ${url} não esta OK&quot;</span><span class="p">);</span> + <span class="p">}</span> + <span class="p">}</span> + +<span class="na"> [FunctionName(&quot;HttpCheck&quot;)]</span> + <span class="k">public</span> <span class="k">static</span> <span class="k">void</span> <span class="nf">Run</span><span class="p">([</span><span class="n">TimerTrigger</span><span class="p">(</span><span class="s">&quot;0 */5 * * * *&quot;</span><span class="p">)]</span><span class="n">TimerInfo</span> <span class="n">myTimer</span><span class="p">,</span> <span class="n">ILogger</span> <span class="n">log</span><span class="p">)</span> + <span class="p">{</span> + <span class="kt">var</span> <span class="n">urls</span> <span class="p">=</span> <span class="k">new</span><span class="p">[]{</span><span class="s">&quot;https://www.sipmann.com&quot;</span><span class="p">,</span> <span class="s">&quot;https://www.canezecanez.com.br&quot;</span><span class="p">};</span> + + <span class="c1">// Start every request and wait for them all to complete</span> + <span class="n">Task</span><span class="p">.</span><span class="n">WaitAll</span><span class="p">(</span><span class="n">urls</span><span class="p">.</span><span class="n">Select</span><span class="p">(</span><span class="n">url</span> <span class="p">=&gt;</span> <span class="n">GetTask</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">log</span><span class="p">)).</span><span class="n">ToArray</span><span class="p">());</span> + <span class="n">log</span><span class="p">.</span><span class="n">LogInformation</span><span class="p">(</span><span class="err">$</span><span class="s">&quot;Finalizou a fila&quot;</span><span class="p">);</span> + <span class="p">}</span> + <span class="p">}</span> +<span class="p">}</span> +</code></pre></div> + +<p>Now you can enhance the function and maybe send some alerts like a Telegram message when one of your sites went down.</p>Zabbix ICMP pinger processes more than 75%2020-05-25T16:00:00-03:002020-05-25T16:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-05-25:/pt/zabbix-icmp-pinger-processes-more-than-75.html<p>Então o seu systema de monitoramento creasceu e o seu Zabbix começou a printar "<em>Zabbix icmp pinger processes more than 75% busy</em>" no seu dashboard.</p> +<p><img alt="Dashboard do zabbix avisando sobre o erro" src="/images/zabbix_pinger01.png"></p> +<p>Tudo que você tem a fazer é abrir o seu arquivo de configuração (<code>/etc/zabbix/zabbix_server.conf</code>) e localizar a tag chamada <code>StartPingers</code>. Ela deve …</p><p>Então o seu systema de monitoramento creasceu e o seu Zabbix começou a printar "<em>Zabbix icmp pinger processes more than 75% busy</em>" no seu dashboard.</p> +<p><img alt="Dashboard do zabbix avisando sobre o erro" src="/images/zabbix_pinger01.png"></p> +<p>Tudo que você tem a fazer é abrir o seu arquivo de configuração (<code>/etc/zabbix/zabbix_server.conf</code>) e localizar a tag chamada <code>StartPingers</code>. Ela deve estar comentáda por padrão. Descomente a lina e define o seu valor para algo como 3 or 4. Deve resolver seu problema, ao menos até um próximo crescimento do seu monitoramento.</p> +<div class="highlight"><pre><span></span><code><span class="c1">### Option: StartPingers</span> +<span class="c1"># Number of pre-forked instances of ICMP pingers.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 0-1000</span> +<span class="c1"># Default:</span> +<span class="nv">StartPingers</span><span class="o">=</span><span class="m">4</span> +</code></pre></div>Zabbix ICMP pinger processes more than 75%2020-05-25T16:00:00-03:002020-05-25T16:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-05-25:/en/zabbix-icmp-pinger-processes-more-than-75.html<p>So your monitoring sytems have grown and your zabbix started loggin "Zabbix icmp pinger processes more than 75% busy" at the dashboard.</p> +<p><img alt="Dashboard do zabbix avisando sobre o erro" src="/images/zabbix_pinger01.png"></p> +<p>All you have to do is open your config file (<code>/etc/zabbix/zabbix_server.conf</code>) and find the a tag named <code>StartPingers</code>. It'll be commented by default. Uncomment it …</p><p>So your monitoring sytems have grown and your zabbix started loggin "Zabbix icmp pinger processes more than 75% busy" at the dashboard.</p> +<p><img alt="Dashboard do zabbix avisando sobre o erro" src="/images/zabbix_pinger01.png"></p> +<p>All you have to do is open your config file (<code>/etc/zabbix/zabbix_server.conf</code>) and find the a tag named <code>StartPingers</code>. It'll be commented by default. Uncomment it and set it's value to something like 3 or 4. It should solve your problem.</p> +<div class="highlight"><pre><span></span><code><span class="c1">### Option: StartPingers</span> +<span class="c1"># Number of pre-forked instances of ICMP pingers.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 0-1000</span> +<span class="c1"># Default:</span> +<span class="nv">StartPingers</span><span class="o">=</span><span class="m">4</span> +</code></pre></div> + +<h2>How many Pingers do I need?</h2> +<p>Well, there is no exact answer to this. If you set it too high, you'll be wasting resources. The best way to solve, it's increasing them as soon as you notice the percentage growing.</p>Zabbix Server Out of Memory2020-02-27T19:00:00-03:002020-02-27T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-02-27:/pt/zabbix-server-out-of-memory-crash.html<p>Você tem um servidor Zabbix crashando e observando o arquivo de log <code>/var/log/zabbix/zabbix_server.log</code> você localiza a seguinte mensagem referênciando falta de memória?</p> +<div class="highlight"><pre><span></span><code>__mem_malloc: skipped <span class="m">0</span> asked <span class="m">24</span> skip_min <span class="m">18446744073709551615</span> skip_max <span class="m">0</span> +<span class="o">[</span>file:dbconfig.c,line:94<span class="o">]</span> __zbx_mem_realloc<span class="o">()</span>: out of memory <span class="o">(</span>requested <span class="m">16</span> bytes<span class="o">)</span> +<span class="o">[</span>file:dbconfig.c …</code></pre></div><p>Você tem um servidor Zabbix crashando e observando o arquivo de log <code>/var/log/zabbix/zabbix_server.log</code> você localiza a seguinte mensagem referênciando falta de memória?</p> +<div class="highlight"><pre><span></span><code>__mem_malloc: skipped <span class="m">0</span> asked <span class="m">24</span> skip_min <span class="m">18446744073709551615</span> skip_max <span class="m">0</span> +<span class="o">[</span>file:dbconfig.c,line:94<span class="o">]</span> __zbx_mem_realloc<span class="o">()</span>: out of memory <span class="o">(</span>requested <span class="m">16</span> bytes<span class="o">)</span> +<span class="o">[</span>file:dbconfig.c,line:94<span class="o">]</span> __zbx_mem_realloc<span class="o">()</span>: please increase CacheSize configuration parameter +</code></pre></div> + +<p>Apesar da simples solução para o erro, isso acaba sendo um problema comum em servidores que tem uma certa quantidade de itens sendo monitorados (servidores, switches, firewalls, bancos, etc...). Para resolver o problema, vá até o ser arquivo <code>zabbix_server.conf</code> e procure pela propriedade <code>CacheSize</code> e sete o seu valor para uma quantidade maior. O seu valor default deve ser algo como 8M. Em clientes que tenham algo como 4 servidores, 7 firewalls/appliances, e algumas outras coisas (bancos, apps), 32M deve resolver o problema, mas você pode setar até algo como 8G (ressalto que mais memória nem sempre é melhor).</p> +<p>Até breve.</p>Zabbix Server Out of Memory2020-02-27T19:00:00-03:002020-02-27T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-02-27:/en/zabbix-server-out-of-memory-crash.html<p>Do you have a crashing Zabbix Server and looking through the log <code>/var/log/zabbix/zabbix_server.log</code> you see the following out of memory message?</p> +<div class="highlight"><pre><span></span><code>__mem_malloc: skipped <span class="m">0</span> asked <span class="m">24</span> skip_min <span class="m">18446744073709551615</span> skip_max <span class="m">0</span> +<span class="o">[</span>file:dbconfig.c,line:94<span class="o">]</span> __zbx_mem_realloc<span class="o">()</span>: out of memory <span class="o">(</span>requested <span class="m">16</span> bytes<span class="o">)</span> +<span class="o">[</span>file:dbconfig.c,line …</code></pre></div><p>Do you have a crashing Zabbix Server and looking through the log <code>/var/log/zabbix/zabbix_server.log</code> you see the following out of memory message?</p> +<div class="highlight"><pre><span></span><code>__mem_malloc: skipped <span class="m">0</span> asked <span class="m">24</span> skip_min <span class="m">18446744073709551615</span> skip_max <span class="m">0</span> +<span class="o">[</span>file:dbconfig.c,line:94<span class="o">]</span> __zbx_mem_realloc<span class="o">()</span>: out of memory <span class="o">(</span>requested <span class="m">16</span> bytes<span class="o">)</span> +<span class="o">[</span>file:dbconfig.c,line:94<span class="o">]</span> __zbx_mem_realloc<span class="o">()</span>: please increase CacheSize configuration parameter +</code></pre></div> + +<p>Besides the clear solution to the error, that's a common issue on servers that have a few monitoring items on it (servers, switches, firewalls, databases, etc...). To solve, go to your zabbix_server.conf and look for the CacheSize property and set it to a higher value. Its default should be 8M. At a customer that has somewhere between 4 servers, 7 firewalls/appliances, and a few other things, a 32M did the job, but you can set up to 8G.</p> +<p>See ya folks.</p>Removendo um usuário de uma base SQL Server2019-09-06T07:00:00-03:002020-10-21T18:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2019-09-06:/pt/removing-user-from-sql-server-database.html<p>O seu cliente lhe pede com urgência para <em>dropar</em> um usuário da sua base MsSQL Server, mas você trava com o seguinte aviso de erro:</p> +<div class="highlight"><pre><span></span><code><span class="n">Error</span><span class="o">:</span> <span class="mi">15138</span> <span class="n">The</span> <span class="n">database</span> <span class="n">principal</span> <span class="n">owns</span> <span class="n">a</span> <span class="n">schema</span> <span class="k">in</span> <span class="n">the</span> <span class="n">database</span><span class="o">,</span> <span class="n">and</span> <span class="n">cannot</span> <span class="n">be</span> <span class="n">dropped</span><span class="o">.</span> +</code></pre></div> + +<p>Se você não possui (ou no momento não consegue acesso …</p><p>O seu cliente lhe pede com urgência para <em>dropar</em> um usuário da sua base MsSQL Server, mas você trava com o seguinte aviso de erro:</p> +<div class="highlight"><pre><span></span><code><span class="n">Error</span><span class="o">:</span> <span class="mi">15138</span> <span class="n">The</span> <span class="n">database</span> <span class="n">principal</span> <span class="n">owns</span> <span class="n">a</span> <span class="n">schema</span> <span class="k">in</span> <span class="n">the</span> <span class="n">database</span><span class="o">,</span> <span class="n">and</span> <span class="n">cannot</span> <span class="n">be</span> <span class="n">dropped</span><span class="o">.</span> +</code></pre></div> + +<p>Se você não possui (ou no momento não consegue acesso) ao SSMS (SQL Server Management Studio) para verificar quais schemas ou objetos o usuário é "dono", a seguinte SQL vai resolver o problema.</p> +<div class="highlight"><pre><span></span><code><span class="k">USE</span><span class="w"> </span><span class="o">[</span><span class="n">DATABASENAME</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> + +<span class="k">select</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Objeto</span><span class="p">,</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Owner</span><span class="w"></span> +<span class="k">from</span><span class="w"> </span><span class="n">sys</span><span class="p">.</span><span class="n">schemas</span><span class="w"> </span><span class="n">so</span><span class="w"></span> +<span class="k">inner</span><span class="w"> </span><span class="k">join</span><span class="w"> </span><span class="n">sysusers</span><span class="w"> </span><span class="n">su</span><span class="w"> </span><span class="k">on</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">principal_id</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">uid</span><span class="w"></span> +<span class="k">where</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">&#39;username&#39;</span><span class="w"></span> + +<span class="k">select</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Objeto</span><span class="p">,</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Owner</span><span class="p">,</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">xtype</span><span class="w"> </span><span class="n">Tipo</span><span class="w"></span> +<span class="k">from</span><span class="w"> </span><span class="n">sys</span><span class="p">.</span><span class="n">sysobjects</span><span class="w"> </span><span class="n">so</span><span class="w"></span> +<span class="k">inner</span><span class="w"> </span><span class="k">join</span><span class="w"> </span><span class="n">sysusers</span><span class="w"> </span><span class="n">su</span><span class="w"> </span><span class="k">on</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">uid</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">uid</span><span class="w"></span> +<span class="k">where</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">&#39;username&#39;</span><span class="w"></span> +</code></pre></div> + +<p>Assim que você tiver os objetos/schemas que o usuário é dono, você pode alterar os mesmos com a seguinte SQL (exemplo de troca de schema):</p> +<div class="highlight"><pre><span></span><code><span class="k">USE</span><span class="w"> </span><span class="o">[</span><span class="n">DATABASENAME</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +<span class="k">ALTER</span><span class="w"> </span><span class="k">AUTHORIZATION</span><span class="w"> </span><span class="k">ON</span><span class="w"> </span><span class="k">SCHEMA</span><span class="o">::[</span><span class="n">db_datareader</span><span class="o">]</span><span class="w"> </span><span class="k">TO</span><span class="w"> </span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="w"> </span><span class="c1">-- username do novo dono</span> +<span class="k">ALTER</span><span class="w"> </span><span class="k">AUTHORIZATION</span><span class="w"> </span><span class="k">ON</span><span class="w"> </span><span class="k">SCHEMA</span><span class="o">::[</span><span class="n">db_datawriter</span><span class="o">]</span><span class="w"> </span><span class="k">TO</span><span class="w"> </span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +</code></pre></div> + +<p>Então, você pode dropar o usuário <code>DROP USER [username]</code>.</p>Removing a user from SQL Server database who owns a schema2019-09-06T07:00:00-03:002020-10-21T18:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2019-09-06:/en/removing-user-from-sql-server-database.html<p>Your customer urge you to drop a user from the MsSQL Server database, but you stuck with the following related error:</p> +<div class="highlight"><pre><span></span><code><span class="n">Error</span><span class="o">:</span> <span class="mi">15138</span> <span class="n">The</span> <span class="n">database</span> <span class="n">principal</span> <span class="n">owns</span> <span class="n">a</span> <span class="n">schema</span> <span class="k">in</span> <span class="n">the</span> <span class="n">database</span><span class="o">,</span> <span class="n">and</span> <span class="n">cannot</span> <span class="n">be</span> <span class="n">dropped</span><span class="o">.</span> +</code></pre></div> + +<p>That means that the user owns one or more shcemas of your database. If …</p><p>Your customer urge you to drop a user from the MsSQL Server database, but you stuck with the following related error:</p> +<div class="highlight"><pre><span></span><code><span class="n">Error</span><span class="o">:</span> <span class="mi">15138</span> <span class="n">The</span> <span class="n">database</span> <span class="n">principal</span> <span class="n">owns</span> <span class="n">a</span> <span class="n">schema</span> <span class="k">in</span> <span class="n">the</span> <span class="n">database</span><span class="o">,</span> <span class="n">and</span> <span class="n">cannot</span> <span class="n">be</span> <span class="n">dropped</span><span class="o">.</span> +</code></pre></div> + +<p>That means that the user owns one or more shcemas of your database. If you don't have access to the SSMS to see which schema or objects the user owns, the following SQL should do the job.</p> +<div class="highlight"><pre><span></span><code><span class="k">USE</span><span class="w"> </span><span class="o">[</span><span class="n">DATABASENAME</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> + +<span class="k">select</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Objeto</span><span class="p">,</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Owner</span><span class="w"></span> +<span class="k">from</span><span class="w"> </span><span class="n">sys</span><span class="p">.</span><span class="n">schemas</span><span class="w"> </span><span class="n">so</span><span class="w"></span> +<span class="k">inner</span><span class="w"> </span><span class="k">join</span><span class="w"> </span><span class="n">sysusers</span><span class="w"> </span><span class="n">su</span><span class="w"> </span><span class="k">on</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">principal_id</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">uid</span><span class="w"></span> +<span class="k">where</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">&#39;username&#39;</span><span class="w"></span> + +<span class="k">select</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Objeto</span><span class="p">,</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Owner</span><span class="p">,</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">xtype</span><span class="w"> </span><span class="n">Tipo</span><span class="w"></span> +<span class="k">from</span><span class="w"> </span><span class="n">sys</span><span class="p">.</span><span class="n">sysobjects</span><span class="w"> </span><span class="n">so</span><span class="w"></span> +<span class="k">inner</span><span class="w"> </span><span class="k">join</span><span class="w"> </span><span class="n">sysusers</span><span class="w"> </span><span class="n">su</span><span class="w"> </span><span class="k">on</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">uid</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">uid</span><span class="w"></span> +<span class="k">where</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">&#39;username&#39;</span><span class="w"></span> +</code></pre></div> + +<p>Once you have the objects/schemas owned by the user, you can change them with the following SQL (schema change sample):</p> +<div class="highlight"><pre><span></span><code><span class="k">USE</span><span class="w"> </span><span class="o">[</span><span class="n">DATABASENAME</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +<span class="k">ALTER</span><span class="w"> </span><span class="k">AUTHORIZATION</span><span class="w"> </span><span class="k">ON</span><span class="w"> </span><span class="k">SCHEMA</span><span class="o">::[</span><span class="n">db_datareader</span><span class="o">]</span><span class="w"> </span><span class="k">TO</span><span class="w"> </span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="w"> </span><span class="c1">-- new owner username</span> +<span class="k">ALTER</span><span class="w"> </span><span class="k">AUTHORIZATION</span><span class="w"> </span><span class="k">ON</span><span class="w"> </span><span class="k">SCHEMA</span><span class="o">::[</span><span class="n">db_datawriter</span><span class="o">]</span><span class="w"> </span><span class="k">TO</span><span class="w"> </span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +</code></pre></div> + +<p>Then you're ready to drop the user <code>DROP USER [username]</code></p> +<h2>How to list all the schemas and it's owners?</h2> +<p>Here's a script to list schemas and it's owners.</p> +<div class="highlight"><pre><span></span><code><span class="k">USE</span><span class="w"> </span><span class="o">[</span><span class="n">DATABASENAME</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +<span class="k">SELECT</span><span class="w"></span> +<span class="w"> </span><span class="nf">schema_name</span><span class="p">(</span><span class="nf">schema_id</span><span class="p">)</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="n">schemaname</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="nf">user_name</span><span class="p">(</span><span class="n">schm</span><span class="p">.</span><span class="n">principal_id</span><span class="p">)</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="n">username</span><span class="p">,</span><span class="w"> </span><span class="o">*</span><span class="w"></span> +<span class="k">FROM</span><span class="w"> </span><span class="n">sys</span><span class="p">.</span><span class="n">schemas</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="n">schm</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +</code></pre></div>Resolvendo java.net.SocketException: Protocol family unavailable em Java + Docker + WildFly2018-03-04T17:40:00-03:002018-03-04T17:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-03-04:/pt/socketException-protocol-family-unavailable-java-docker-wildfly.html<p>Nos últimos dias eu estou brincando com o <a class="reference external" href="http://wildfly-swarm.io/">WildFly Swarm</a> e decidi fazer o deploy de uma aplicação simples com Docker. Deveria funcionar bem, ao menos é o que pensava. Construí um container com o seguinte Dockerfile e ao invés de obter uma aplicação web, tudo que eu obtive foi …</p><p>Nos últimos dias eu estou brincando com o <a class="reference external" href="http://wildfly-swarm.io/">WildFly Swarm</a> e decidi fazer o deploy de uma aplicação simples com Docker. Deveria funcionar bem, ao menos é o que pensava. Construí um container com o seguinte Dockerfile e ao invés de obter uma aplicação web, tudo que eu obtive foi o erro <cite>java.net.SocketException: Protocol family unavailable</cite>.</p> +<div class="highlight"><pre><span></span><span class="k">FROM</span> <span class="s">java:openjdk-8-jdk</span> + +<span class="k">COPY</span> target/issues.jar /opt/issues.jar + +<span class="k">EXPOSE</span><span class="s"> 8080</span> + +<span class="k">CMD</span> <span class="p">[</span><span class="s2">&quot;java&quot;</span><span class="p">,</span><span class="s2">&quot;-jar&quot;</span><span class="p">,</span><span class="s2">&quot;/opt/issues.jar&quot;</span><span class="p">]</span> +</pre></div> +<p>Por alguma razão, WildFly e Java, ambos decidiram utilizar um protocolo IPv6 na interface de rede no Docker invés da v4, então tudo que você tem que fazer é falar ao Java que deve dar preferência em utilizar o IPv4 com a seguinte configuração no seu arquivo pom.xml dentro da tag do plugin WildFly.</p> +<div class="highlight"><pre><span></span><span class="nt">&lt;plugin&gt;</span> + <span class="nt">&lt;groupId&gt;</span>org.wildfly.swarm<span class="nt">&lt;/groupId&gt;</span> + <span class="nt">&lt;artifactId&gt;</span>wildfly-swarm-plugin<span class="nt">&lt;/artifactId&gt;</span> + <span class="nt">&lt;version&gt;</span>2018.2.0<span class="nt">&lt;/version&gt;</span> + + <span class="c">&lt;!-- ADICIONE ISTO --&gt;</span> + <span class="nt">&lt;configuration&gt;</span> + <span class="nt">&lt;mainClass&gt;</span>org.wildfly.swarm.examples.netflix.ribbon.frontend.Main<span class="nt">&lt;/mainClass&gt;</span> + <span class="nt">&lt;properties&gt;</span> + <span class="nt">&lt;java.net.preferIPv4Stack&gt;</span>true<span class="nt">&lt;/java.net.preferIPv4Stack&gt;</span> + <span class="nt">&lt;/properties&gt;</span> + <span class="nt">&lt;/configuration&gt;</span> +</pre></div> +<p>Outra forma de solucionar o problema, é adicionando a mesma propriedade ao comando de run no seu Dockerfile. Então, fica a seu critério onde adicionar. Abaixo a solução utilizando o Dockerfile.</p> +<div class="highlight"><pre><span></span><span class="k">FROM</span> <span class="s">java:openjdk-8-jdk</span> +<span class="k">ENV</span> <span class="nv">JAVA_OPTS</span><span class="o">=</span><span class="s2">&quot;-Djava.net.preferIPv4Stack=true -Djava.net.preferIPv4Addresses=true&quot;</span> + +<span class="k">COPY</span> target/issues.jar /opt/issues.jar + +<span class="k">EXPOSE</span><span class="s"> 8080</span> + +<span class="k">ENTRYPOINT</span> <span class="nb">exec</span> java <span class="nv">$JAVA_OPTS</span> -jar /opt/issues.jar +</pre></div> +Solving java.net.SocketException: Protocol family unavailable on a Java + Docker + WildFly2018-03-04T17:40:00-03:002018-03-04T17:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-03-04:/en/socketException-protocol-family-unavailable-java-docker-wildfly.html<p>On the last days I've been playing with <a class="reference external" href="http://wildfly-swarm.io/">WildFly Swarm</a> and I decided to deploy a simple app with Docker. Should work fine, at least that was what I thought. Built a container with the following Dockerfile and instead of a working web app, all that I got was the …</p><p>On the last days I've been playing with <a class="reference external" href="http://wildfly-swarm.io/">WildFly Swarm</a> and I decided to deploy a simple app with Docker. Should work fine, at least that was what I thought. Built a container with the following Dockerfile and instead of a working web app, all that I got was the error <cite>java.net.SocketException: Protocol family unavailable</cite>.</p> +<div class="highlight"><pre><span></span><span class="k">FROM</span> <span class="s">java:openjdk-8-jdk</span> + +<span class="k">COPY</span> target/issues.jar /opt/issues.jar + +<span class="k">EXPOSE</span><span class="s"> 8080</span> + +<span class="k">CMD</span> <span class="p">[</span><span class="s2">&quot;java&quot;</span><span class="p">,</span><span class="s2">&quot;-jar&quot;</span><span class="p">,</span><span class="s2">&quot;/opt/issues.jar&quot;</span><span class="p">]</span> +</pre></div> +<p>For some reason, WildFly and Java decided to use the IPv6 network interface from Docker instead the v4, so all you have to do is tell Java to prefer IPv4 instead with the following configuration option in your pom.xml file inside your WildFly plugin.</p> +<div class="highlight"><pre><span></span><span class="nt">&lt;plugin&gt;</span> + <span class="nt">&lt;groupId&gt;</span>org.wildfly.swarm<span class="nt">&lt;/groupId&gt;</span> + <span class="nt">&lt;artifactId&gt;</span>wildfly-swarm-plugin<span class="nt">&lt;/artifactId&gt;</span> + <span class="nt">&lt;version&gt;</span>2018.2.0<span class="nt">&lt;/version&gt;</span> + + <span class="c">&lt;!-- ADD THIS --&gt;</span> + <span class="nt">&lt;configuration&gt;</span> + <span class="nt">&lt;mainClass&gt;</span>org.wildfly.swarm.examples.netflix.ribbon.frontend.Main<span class="nt">&lt;/mainClass&gt;</span> + <span class="nt">&lt;properties&gt;</span> + <span class="nt">&lt;java.net.preferIPv4Stack&gt;</span>true<span class="nt">&lt;/java.net.preferIPv4Stack&gt;</span> + <span class="nt">&lt;/properties&gt;</span> + <span class="nt">&lt;/configuration&gt;</span> +</pre></div> +<p>Another way to solve is adding the same properties to the run command at the Dockerfile, so you choose where you'll add it. Bellow the Dockerfile solution.</p> +<div class="highlight"><pre><span></span><span class="k">FROM</span> <span class="s">java:openjdk-8-jdk</span> +<span class="k">ENV</span> <span class="nv">JAVA_OPTS</span><span class="o">=</span><span class="s2">&quot;-Djava.net.preferIPv4Stack=true -Djava.net.preferIPv4Addresses=true&quot;</span> + +<span class="k">COPY</span> target/issues.jar /opt/issues.jar + +<span class="k">EXPOSE</span><span class="s"> 8080</span> + +<span class="k">ENTRYPOINT</span> <span class="nb">exec</span> java <span class="nv">$JAVA_OPTS</span> -jar /opt/issues.jar +</pre></div> +Menu dinâmico com as apps do django2018-01-21T21:17:00-02:002018-01-21T21:17:00-02:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-01-21:/pt/menu-dinamico-com-apps-do-django.html<p>Digamos que sua empresa trabalha com Django desenvolvendo aplicações cujas apps são plugaveis e reutilizáveis. Por que não se aproveitar de um certo padrão de desenvolvimento para desenvolver menus que se modificam de acordo com as apps que estão no projeto? Como o objetivo aqui não é desenvolver uma app …</p><p>Digamos que sua empresa trabalha com Django desenvolvendo aplicações cujas apps são plugaveis e reutilizáveis. Por que não se aproveitar de um certo padrão de desenvolvimento para desenvolver menus que se modificam de acordo com as apps que estão no projeto? Como o objetivo aqui não é desenvolver uma app em si, vamos utilizar um projeto com algumas de modelo. Se desejar estudar mais sobre desenvolvimento Django, a documentação é muito boa, mas também temos blogs e sites excelentes sobre o assunto.</p> +<p>Para conseguirmos atingir esse objetivo, vamos utilizar a api <a class="reference external" href="https://docs.djangoproject.com/en/2.0/ref/settings/#installed-apps">Django.apps</a> que está disponível a partir da versão 1.7. +Com esta api, vamos percorrer as apps e se possível, criar um link para uma URL base de cada uma delas. Para começo, baixe os fontes do <a class="reference external" href="https://github.com/sipmann/menusapp-django/releases/tag/v1">projeto aqui</a>, rode o pip install do projeto e no fim, sua estrutura de pastas deve ficar como abaixo.</p> +<div class="highlight"><pre><span></span>../menusapp/ +├── comentarios +│ ├── templates +│ │ └── comentarios +│ │ └── listagem.html +│ ├── __init__.py +│ ├── admin.py +│ ├── apps.py +│ ├── models.py +│ ├── tests.py +│ ├── urls.py +│ └── views.py +├── core +│ ├── templates +│ │ └── core +│ │ └── base.html +│ │ └── listagem.html +│ ├── __init__.py +│ ├── admin.py +│ ├── apps.py +│ ├── models.py +│ ├── tests.py +│ ├── urls.py +│ └── views.py +├── menusapp +│ ├── __init__.py +│ ├── settings.py +│ ├── urls.py +│ └── wsgi.py +└── manage.py +</pre></div> +<p>Rode o projeto e veja como é o seu funcionamento. É na app core que temos a base do nosso HTML, então será nele que iremos trabalhar. Quando se trata de algo que será renderizado no template base, eu gosto muito de utilizar 'template tags' para facilitar. +Neste <a class="reference external" href="http://www.sipmann.com/editando-o-admin-do-django.html">link</a> tem mais um exemplo de utilização de 'template tag' caso esteja interessado.</p> +<p>Vamos então criar uma pasta chamada template_tag e dentro dela a nossa tag. Vamos chamá-la de menus_tag.py. Abaixo vamos ver um pouco da nossa tag. +O código é bem simples e auto explicativo, importamos as bibliotecas necessárias e realizamos o &#64;register da tag com o nome do template que será renderizado. +E por ultimo, retornamos uma tupla de dados para o template.</p> +<div class="livros"> + <div class="recomendacoes">Recomendações</div> + <a rel="noopener" href="https://www.amazon.com.br/gp/product/8575225081/ref=as_li_ss_il?ie=UTF8&linkCode=li2&tag=sipmann-20&linkId=c17fa3ac84e734741a3761e874d7d286" target="_blank"><img border="0" src="//ws-na.amazon-adsystem.com/widgets/q?_encoding=UTF8&ASIN=8575225081&Format=_SL160_&ID=AsinImage&MarketPlace=BR&ServiceVersion=20070822&WS=1&tag=sipmann-20" ></a><img src="https://ir-br.amazon-adsystem.com/e/ir?t=sipmann-20&l=li2&o=33&a=8575225081" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /> + <a rel="noopener" href="https://www.amazon.com.br/gp/product/B074ZTLKHB/ref=as_li_ss_il?ie=UTF8&linkCode=li2&tag=sipmann-20&linkId=e2f37c07da2dc4111ae47854b205d01a" target="_blank"><img border="0" src="//ws-na.amazon-adsystem.com/widgets/q?_encoding=UTF8&ASIN=B074ZTLKHB&Format=_SL160_&ID=AsinImage&MarketPlace=BR&ServiceVersion=20070822&WS=1&tag=sipmann-20" ></a><img src="https://ir-br.amazon-adsystem.com/e/ir?t=sipmann-20&l=li2&o=33&a=B074ZTLKHB" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /> +</div><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django</span> <span class="kn">import</span> <span class="n">template</span> +<span class="kn">from</span> <span class="nn">django.apps</span> <span class="kn">import</span> <span class="n">apps</span> + +<span class="c1">#Carrega o registro de template tags</span> +<span class="n">register</span> <span class="o">=</span> <span class="n">template</span><span class="o">.</span><span class="n">Library</span><span class="p">()</span> + +<span class="c1">#Registra o metodo a seguir como uma inclusion_tag indicando o template a ser renderizado</span> +<span class="nd">@register</span><span class="o">.</span><span class="n">inclusion_tag</span><span class="p">(</span><span class="s1">&#39;menus_por_app.html&#39;</span><span class="p">)</span> +<span class="k">def</span> <span class="nf">menus_por_app</span><span class="p">():</span> + <span class="n">lst</span> <span class="o">=</span> <span class="n">apps</span><span class="o">.</span><span class="n">get_app_configs</span><span class="p">()</span> + <span class="k">return</span> <span class="p">{</span> <span class="s1">&#39;lst_apps&#39;</span> <span class="p">:</span> <span class="n">lst</span> <span class="p">}</span> +</pre></div> +<p>O template está abaixo e é simplesmente um for percorrendo as apps e gerando uma lista com os seus menus. As outras propriedades você pode ver direto na <a class="reference external" href="https://docs.djangoproject.com/en/2.0/ref/applications/#django.apps.AppConfig">documentação</a>. +Algumas ressalvas para o que foi feito por questões de praticidade para uso posterior, utilizei um with para concatenar e gerar a url e criei um apelido para a url para validar a existência da mesma. Fora isto, nada de novo.</p> +<div class="highlight"><pre><span></span>{% if not lst_apps %} + <span class="p">&lt;</span><span class="nt">p</span><span class="p">&gt;</span>Nenhuma app<span class="p">&lt;/</span><span class="nt">p</span><span class="p">&gt;</span> + {% else %} + <span class="p">&lt;</span><span class="nt">ul</span><span class="p">&gt;</span> + {% for app in lst_apps %} + {% with app.name|add:&quot;:listagem&quot; as link %} + {% url link as the_url %} + {% if the_url %} + <span class="p">&lt;</span><span class="nt">li</span><span class="p">&gt;</span> + <span class="p">&lt;</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">&quot;{% url link %}&quot;</span><span class="p">&gt;</span>{{ app.verbose_name|truncatechars:30 }}<span class="p">&lt;/</span><span class="nt">a</span><span class="p">&gt;</span> + <span class="p">&lt;/</span><span class="nt">li</span><span class="p">&gt;</span> + {% endif %} + {% endwith %} + {% endfor %} + <span class="p">&lt;/</span><span class="nt">ul</span><span class="p">&gt;</span> + {% endif %} +</pre></div> +<img alt="Resultado final" src="/images/menu_apps.png" /> +<p>No final, o resultado obtido deve ser semelhante ao acima. Repare que está listando as duas aplicações. E acima de tudo, repare que só serão exibidos os links cuja app tenha um namespace de mesmo nome e uma url de nome <cite>listagem</cite>. +A estrutura final pode ser vista abaixo. Atente-se aos nomes tanto das pastas quanto dos arquivos, pois qualquer diferença pode causar o não funcionamento.</p> +<div class="highlight"><pre><span></span>../menusapp/ +├── comentarios +│ ├── templates +│ │ └── comentarios +│ │ └── listagem.html +│ ├── __init__.py +│ ├── admin.py +│ ├── apps.py +│ ├── models.py +│ ├── tests.py +│ ├── urls.py +│ └── views.py +├── core +│ ├── templates +│ │ └── core +│ │ │ └── base.html +│ │ │ └── listagem.html +│ │ └── menus_por_app.html +│ ├── templatetags +│ │ ├── __init__.py +│ │ └── menus_tag.py +│ ├── __init__.py +│ ├── admin.py +│ ├── apps.py +│ ├── models.py +│ ├── tests.py +│ ├── urls.py +│ └── views.py +├── menusapp +│ ├── __init__.py +│ ├── settings.py +│ ├── urls.py +│ └── wsgi.py +└── manage.py +</pre></div> +<p>Espero que tenham gostado, críticas e sugestões são bem-vindas. <a class="reference external" href="https://github.com/sipmann/menusapp-django/releases/tag/v2">Fontes do Projeto</a></p> +Scripts de inicialização no raspberry pi2017-10-08T18:00:00-03:002017-10-08T18:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2017-10-08:/pt/script-de-inicializacao-raspberry.html<p>Instalei essa semana o <a class="reference external" href="https://gitea.io">gitea</a> no meu raspberry pi B + e queria iniciar ele no boot... Não sou profundo conhecedor de linux, então, logo não sabia como fazer isto da melhor forma. +As versões atuais do Raspbian utilizam o <cite>systemd</cite> para gerenciar os serviços e confesso que nunca havia utilizado …</p><p>Instalei essa semana o <a class="reference external" href="https://gitea.io">gitea</a> no meu raspberry pi B + e queria iniciar ele no boot... Não sou profundo conhecedor de linux, então, logo não sabia como fazer isto da melhor forma. +As versões atuais do Raspbian utilizam o <cite>systemd</cite> para gerenciar os serviços e confesso que nunca havia utilizado o systemctl para nada.</p> +<p>Vamos começa criando um arquivo de serviço dentro da pasta <cite>/etc/systemd/system</cite>, vale ressaltar que a pasta <cite>system</cite> deve (em teoria) ser reservada para pacotes do sistema. +Vamos criar o arquivo com o nome <cite>gitea.service</cite> dentro da pasta antes mencionada. Abaixo podemos ver como ficou o arquivo e um detalhamento após ele.</p> +<div class="highlight"><pre><span></span><span class="o">[</span>Unit<span class="o">]</span> +<span class="nv">Description</span><span class="o">=</span>Gitea Service +<span class="nv">After</span><span class="o">=</span>network.target + +<span class="o">[</span>Service<span class="o">]</span> +<span class="nv">Type</span><span class="o">=</span>simple +<span class="nv">User</span><span class="o">=</span>root +<span class="nv">WorkingDirectory</span><span class="o">=</span>/root/ +<span class="nv">ExecStart</span><span class="o">=</span>/root/gitea web +<span class="nv">Restart</span><span class="o">=</span>on-abort +</pre></div> +<p>A composição do arquivo é bem simples, mas vamos a alguns detalhes. <cite>Type</cite> possui várias opções (simple, forking, oneshot), utilizamos <cite>simple</cite> uma vez que o nosso processo executara, permanecerá rodando e não executa um fork de processo. +Fork como acabo de comentar, deve ser utilizado caso o processo que for executando disparar mais processos. User irá definir o usuário do processo. <cite>WorkingDirectory</cite> definira onde o processo terá a sua base de execução, como o gitea esta localizada na pasta root, +aponto para lá. O ExecStart é bem simples e direto, deve chamar a execução do processo passando parametros caso seja necessário. O <cite>Restart</cite> é o que nos garantirá que o serviço permanecerá rodando caso haja algum imprevisto (exceto o fato de um usuário chamar o stop).</p> +<p>Salve o arquivo e vamos rodar um refresh para o SO perceber o novo serviço. Assim rodamos <cite>systemctl daemon-reload</cite>. Sempre que alterarmos um serviço ou criarmos um novo, este comando deve ser executado, caso contrário o próprio systemctl pode lhe alertar da necessidade. +Após reacarregar os serviços, vamos habilitar o serviço que criamos rodando <cite>systemctl enable gitea</cite>, feito isto temos alguns comandos uteis.</p> +<ul class="simple"> +<li>systemctl start gitea</li> +<li>systemctl stop gitea</li> +<li>systemctl status gitea</li> +</ul> +<p>O comando de status pode ser visto como exemplo abaixo.</p> +<div class="highlight"><pre><span></span>● gitea.service - Gitea Service + Loaded: loaded <span class="o">(</span>/etc/systemd/system/gitea.service<span class="p">;</span> enabled<span class="p">;</span> vendor preset: enabled<span class="o">)</span> + Active: active <span class="o">(</span>running<span class="o">)</span> since Wed <span class="m">2017</span>-10-04 <span class="m">00</span>:37:34 UTC<span class="p">;</span> 52min ago +Main PID: <span class="m">1087</span> <span class="o">(</span>gitea<span class="o">)</span> + CGroup: /system.slice/gitea.service + └─1087 /root/gitea web + +Oct <span class="m">04</span> <span class="m">00</span>:38:31 gitserver gitea<span class="o">[</span><span class="m">1087</span><span class="o">]</span>: <span class="o">[</span>Macaron<span class="o">]</span> <span class="m">2017</span>-10-04 <span class="m">00</span>:38:31: Completed /explore/users <span class="m">200</span> OK in <span class="m">80</span>.106173ms +Oct <span class="m">04</span> <span class="m">00</span>:38:31 gitserver gitea<span class="o">[</span><span class="m">1087</span><span class="o">]</span>: <span class="o">[</span>Macaron<span class="o">]</span> <span class="m">2017</span>-10-04 <span class="m">00</span>:38:31: Started GET /img/favicon.png <span class="k">for</span> <span class="m">192</span>.168.1.4 +Oct <span class="m">04</span> <span class="m">00</span>:38:31 gitserver gitea<span class="o">[</span><span class="m">1087</span><span class="o">]</span>: <span class="o">[</span>Macaron<span class="o">]</span> <span class="o">[</span>Static<span class="o">]</span> Serving /img/favicon.png +</pre></div> +<p>Após estes processos, você pode reiniciar seu raspberry que o gitea irá subir e funcionar. Ressalto que, preste atenção tanto no <cite>WorkingDirectory</cite> quanto no <cite>ExecStart</cite>, no caso do gitea, ele utiliza o workingdir e a forma de start para saber onde irá largar os arquivos por padrão, então ou você configura ele com caminhos absolutos ou cuidar na forma de start (ao menos é o que consegui pegar até agora).</p> +Cool Tools2017-09-17T14:00:00-03:002017-09-17T14:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2017-09-17:/pt/cool-tools.html<p>Com o passar do tempo você vai &quot;encontrando&quot; - e às vezes até mesmo desenvolvendo - algumas ferramentas que tornam o seu dia a dia como desenvolvedor mais fácil. Abaixo seguem algumas das minhas ferramentas que costumo usar. Ressalto que essa lista será (provavelmente) atualizada com o passar do tempo.</p> +<div class="section" id="https-www-gitkraken-com"> +<h2><a class="reference external" href="https://www.gitkraken.com">https://www …</a></h2></div><p>Com o passar do tempo você vai &quot;encontrando&quot; - e às vezes até mesmo desenvolvendo - algumas ferramentas que tornam o seu dia a dia como desenvolvedor mais fácil. Abaixo seguem algumas das minhas ferramentas que costumo usar. Ressalto que essa lista será (provavelmente) atualizada com o passar do tempo.</p> +<div class="section" id="https-www-gitkraken-com"> +<h2><a class="reference external" href="https://www.gitkraken.com">https://www.gitkraken.com</a></h2> +<p>Eu gosto muito de usar git, mas às vezes fico cansado de ter que usar só linha de comando, e achei no GitKreaken uma interface muito legal de se usar.</p> +</div> +<div class="section" id="http-paletton-com"> +<h2><a class="reference external" href="http://paletton.com">http://paletton.com</a></h2> +<p>Toda vez que você vai fazer um novo sistema/site, ou até mesmo trocar o layout de algum já existente, você acaba tendo que montar uma paleta de cores para se utilizar em todo o template.</p> +</div> +<div class="section" id="https-icomoon-io-app-select"> +<h2><a class="reference external" href="https://icomoon.io/app/#/select">https://icomoon.io/app/#/select</a></h2> +<p>Querendo usar ícones como fontes? Vá aí e gere apenas os arquivos que você vai realmente utilizar e economize alguns kbs.</p> +</div> +<div class="section" id="https-syncthing-net"> +<h2><a class="reference external" href="https://syncthing.net/">https://syncthing.net/</a></h2> +<p>Se você procura algum meio de sincronizar seus arquivos entre vários pcs e por algum motivo não quer usar um Google Drive ou DropBox, fica aqui a indicação deste cara.</p> +</div> +<div class="section" id="http-sqitch-org"> +<h2><a class="reference external" href="http://sqitch.org/">http://sqitch.org/</a></h2> +<p>Gerenciamento de versões de um banco de dados pode ser bem complicado e trabalhoso... Manter diversos ambientes (desenvolvimento, homologação, produção) vai dar um trabalho se não utilizar alguma ferramenta. Porque não usar o melhor de gerenciamento de versão (git) e uma ferramenta que se adequa ao que você precisa? sqitch é o cara nessas horas.</p> +</div> +<div class="section" id="http-www-setupmyproject-com"> +<h2><a class="reference external" href="http://www.setupmyproject.com/">http://www.setupmyproject.com/</a></h2> +<p>Preparação de projetos java, com frameworks, bibliotecas, nomenclatura, etc... Rende uma economia de tempo grandiosa e já vem tudo pronto :).</p> +</div> +<div class="section" id="https-www-pexels-com"> +<h2><a class="reference external" href="https://www.pexels.com/">https://www.pexels.com/</a></h2> +<p>Bom site para imagens free stock. Excelente local para conseguir imagens de alta qualidade.</p> +</div> +<div class="section" id="https-heml-io"> +<h2><a class="reference external" href="https://heml.io/">https://heml.io/</a></h2> +<p>&quot;HEML is an open source markup language for building responsive email.&quot; Melhor descrição impossível.</p> +</div> +<div class="section" id="https-www-mockapi-io"> +<h2><a class="reference external" href="https://www.mockapi.io/">https://www.mockapi.io/</a></h2> +<p>Desenvolva mocks para testar seu front-end. Eles geram inclusive uma carga de dados para ser utilizado nos seus testes.</p> +</div> +<div class="section" id="https-undraw-co"> +<h2><a class="reference external" href="https://undraw.co">https://undraw.co</a></h2> +<p>Needing some cool and free ilustrations? Take a look at it.</p> +</div> +<div class="section" id="https-www-audiotool-com-app"> +<h2><a class="reference external" href="https://www.audiotool.com/app/">https://www.audiotool.com/app/</a></h2> +<p>Ferramenta para criar sons, musicas e afins</p> +</div> +<div class="section" id="https-app-cloudskew-com"> +<h2><a class="reference external" href="https://app.cloudskew.com/">https://app.cloudskew.com/</a></h2> +<p>Desenhar projetos de cloud e afins</p> +</div> +<div class="section" id="https-lottiefiles-com"> +<h2><a class="reference external" href="https://lottiefiles.com/">https://lottiefiles.com/</a></h2> +<p>Veja por si mesmo</p> +</div> +Desenvolvendo apps para o FirefoxOS (Parte 1)2014-09-02T19:00:00-03:002014-09-02T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2014-09-02:/pt/desenvolvendo-app-firefoxos.html<h3>Requisitos mínimos?</h3> +<p>Para seguir este tutorial você precisará do <a href="http://nodejs.org/">Nodejs</a>. Utilizaremos ele para automatizar algumas tarefas, como a criação do nosso projeto e até mesmo o empacotamento da app. Estas automatizações se darão pela utilização de algumas aplicações como o <a href="http://yeoman.io/">Yeoman</a> e o <a href="http://gruntjs.com/">Grunt</a> .</p> +<p>Também será necessário o emulador do …</p><h3>Requisitos mínimos?</h3> +<p>Para seguir este tutorial você precisará do <a href="http://nodejs.org/">Nodejs</a>. Utilizaremos ele para automatizar algumas tarefas, como a criação do nosso projeto e até mesmo o empacotamento da app. Estas automatizações se darão pela utilização de algumas aplicações como o <a href="http://yeoman.io/">Yeoman</a> e o <a href="http://gruntjs.com/">Grunt</a> .</p> +<p>Também será necessário o emulador do <a href="https://www.mozilla.org/pt-BR/firefox/os/">FirefoxOS</a>, ele roda através do seu navegador Firefox. Para instalá-lo basta ir no menu <code>Ferramentas &gt; Desenvolvedor web &gt; App Manager</code>, nesta tela basta tentar iniciar o emulador, se não possuir um já instalado, você será solicitado a fazê-lo. Neste tutorial irei utilizar a versão 1.4.</p> +<h3>Preparando o ambiente</h3> +<p>Tendo o Node instalado, vamos instalar o yeoman e o gerador de app para Firefox OS. Atenção para o parâmetro '-g' no processo de instalação, com ele os seus pacotes serão instalados globalmente, e não só para a pasta em que esta o prompt.</p> +<div class="highlight"><pre><span></span><code><span class="err">npm install -g yo</span> +<span class="err">npm install -g generator-firefoxos-app</span> +</code></pre></div> + +<p>Com ambos os pacotes acima instalados, vamos dar início a criação da app. No seu diretório de projetos ou onde desejar criar a app chama o generator instalado.</p> +<div class="highlight"><pre><span></span><code><span class="err">yo firefoxos-app</span> +</code></pre></div> + +<p>Uma vez chamado esse generator, o mesmo irá fazer alguns questionamentos, o primeiro é claro será o nome da sua aplicação, seguido da descrição e o nome do desenvolvedor.</p> +<p>Após a execução do generator, você já terá uma estrutura para desenvolvimento pronta, inclusive com um html inicial, com todas as dependências já instaladas. Vale ressaltar agora algumas tarefas disponíveis no Gruntfile.</p> +<ul> +<li>Default: Irá gerar o pacote de distribuição</li> +<li>Test: Até a presente versão do generator (0.1.3) este processo irá simplesmente rodar o validador jsHint</li> +<li>Server: Irá disponibilizar na porta 9001 um simples servidor para testar a sua app</li> +</ul> +<p>Vamos testar a nossa app. Para tal, rode o comando <code>grunt server</code> e acesse no seu navegador <code>localhost:9001</code> e devemos ver a seguinte app. Caso nenhuma página seja exibida, revise os passos ateriores e verifique se nenhum erro ocorreu.</p> +<p><img alt="App inicial" src="/images/app_inicial.png"></p> +<p>Vale ressaltar que a sua app toda estará dentro de uma pasta também chamada <code>app</code>. Nela você encontrará os seus arquivos .html, .js, .css e demais. Antes de começarmos a codificar a nossa app, vamos ver como se instala a mesma.</p> +<h3>Instalando a app</h3> +<p>Para fins de teste, não é necessário rodar o comando <code>grunt</code>, sendo que ele irá testar o JS e compactar tudo em um arquivo .zip, basta apontar a instalação para a pasta <code>app</code> dentro do seu projeto. "Mas como eu faço isto?".</p> +<p>Indo novamente na <code>App Manager</code>, clicando na lateral esquerda, onde indica "Aplicativos", teremos então disponível no inferior da tela duas opções, vamos nos ater a utilizar a primeira (<code>Adicionar aplicativo hospedado</code>).</p> +<p>Clicando nesta opção vamos navegar até a pasta da app e clicar selecionada. Pronto.</p> +<p>Simples de se instalar, não acha? O Resultado final deve ser semelhante ao abaixo.</p> +<p><img alt="App inicial" src="/images/app_visual_1.png"></p> +<h3>Acessando uma API</h3> +<p>Quando vamos programar algo mais complexo, geralmente vamos utilizar algo como, câmera, rede, lista de contatos, armazenamento e outras possibilidades. Para utilizarmos essas APIs, precisamos - assim como no desenvolvimento para android - especificar para o usuário no momento de instalação. Estes dados de acesso ficam no arquivo <code>manifes.webapp</code>, se você ainda não deu uma olhada neste arquivo, é nele que fica armazenado dados da app, como nome, descrição, versão, localização de ícones e é claro as permissões que a mesma requer.</p> +<p>As permissões ficam na propriedade permissions, na forma de <code>"chave" : True</code>. Algumas das apis são:</p> +<ul> +<li>câmera</li> +<li>contacts</li> +<li>desktop-notification</li> +<li>storage</li> +</ul> +<p>Cada permissão vai mudar o tipo de app que você esta desenvolvendo, mas aí eu sugiro ler mais na MDN <a href="https://developer.mozilla.org/en-US/Apps/Build/App_permissions">aqui</a>. Esse é o básico para iniciar no desenvolvimento de app para FirefoxOS. Na parte dois, vou começar a passar um pouco de código.</p>Editando o Admin do Django2014-05-15T18:00:00-03:002014-05-15T18:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2014-05-15:/pt/editando-o-admin-do-django.html<p>Este artigo foi re-postado no grupo <a class="reference external" href="http://pythonclub.com.br/editando-o-admin-do-django.html">PythonClub</a>. Vamos falar um pouco sobre como customizar o admin do Django. Primeiramente porque? A resposta é bem simples, quero mostrar algo para o usuário sem que ele precise entrar nas apps e fazer alguma consulta para então tomar alguma ação. Alguns exêmplos para …</p><p>Este artigo foi re-postado no grupo <a class="reference external" href="http://pythonclub.com.br/editando-o-admin-do-django.html">PythonClub</a>. Vamos falar um pouco sobre como customizar o admin do Django. Primeiramente porque? A resposta é bem simples, quero mostrar algo para o usuário sem que ele precise entrar nas apps e fazer alguma consulta para então tomar alguma ação. Alguns exêmplos para isto seriam:</p> +<blockquote> +<ul class="simple"> +<li>Exibir as vendas do mês em forma de gráfico por região do país</li> +<li>Exibir os últimos comentários adicionados</li> +<li>Exibir log dos ultimos usuários cadastrados</li> +</ul> +</blockquote> +<p>O que faremos aqui será exibir os últimos comentários ainda não liberados de um sistema de blog. Vale lembrar que aqui não discutiremos sobre os primeiros passos da aplicação. Para seguirmos adiante, vamos assumir que já temos um projeto básico com uma estrutura simples, abaixo a estrutura inicial do nosso projeto.</p> +<div class="highlight"><pre><span></span>../blog/ +├── core +│ ├── __init__.py +│ ├── admin.py +│ ├── models.py +│ ├── tests.py +│ └── views.py +├── blog +│ ├── __init__.py +│ ├── settings.py +│ ├── urls.py +│ └── wsgi.py +└── manage.py +</pre></div> +<p>Para iniciarmos, precisamos da nossa tabela de comentários, vamos usar a mais simples e básica o possível.</p> +<table border="1" class="docutils"> +<colgroup> +<col width="50%" /> +<col width="50%" /> +</colgroup> +<thead valign="bottom"> +<tr><th class="head">Campo</th> +<th class="head">Tipo</th> +</tr> +</thead> +<tbody valign="top"> +<tr><td>nome</td> +<td>Varchar(30)</td> +</tr> +<tr><td>texto</td> +<td>Text</td> +</tr> +<tr><td>liberado</td> +<td>Boolean</td> +</tr> +<tr><td>data</td> +<td>Date</td> +</tr> +</tbody> +</table> +<p>Vamos seguir adiante e alterar a página inicial do admin para listar os últimos comentários de um simples sistema de blog. Para comerçar a editar o admin, precisamos inicialmente copiar o template que desejamos para a pasta uma pasta <cite>admin</cite> dentro ta pasta de templates do nosso projeto. Isto porque o Admin, não passa de uma app como outra qualquer, portanto o sistema de herança vai funcionar aqui, carregamento prioritariamente o seu template. Você pode conseguir o template que desejar (no nosso caso o index.html) dentro do projeto do Django mesmo, no meu caso &quot;C:\Django-1.6.3\django\contrib\admin\templates\admin&quot;.</p> +<div class="highlight"><pre><span></span>../blog/ +├── templates +│ ├── admin +│ │ └── index.html +├── core +</pre></div> +<p>Tire um tempo e brinque um pouco com este template e veja o que acontece se você alterar algumas coisa. Para adicionarmos a nossa listagem, vamos adicionar um painel lateral, para tal vamos adicionar o código abaixo antes do fechamento da ultima tag div. Nele podemos ver uma chamada para uma template_tag, portanto precisamos carrega-la no topo do template.</p> +<div class="highlight"><pre><span></span>{% load comentarios_tag %} +... +... +... +<span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">&quot;module&quot;</span> <span class="na">id</span><span class="o">=</span><span class="s">&quot;ultimos-comentarios&quot;</span><span class="p">&gt;</span> + <span class="p">&lt;</span><span class="nt">h2</span><span class="p">&gt;</span>Ultimos Comentários<span class="p">&lt;/</span><span class="nt">h2</span><span class="p">&gt;</span> + <span class="p">&lt;</span><span class="nt">h3</span><span class="p">&gt;</span>Liberar<span class="p">&lt;/</span><span class="nt">h3</span><span class="p">&gt;</span> + {% comentarios_n_liberados %} +<span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span> +</pre></div> +<p>Esta template trata-se da responsável por fazer a consulta na base de dados e renderizar a nossa lista, portanto ela é uma 'inclusion tag'. Se você não esta familiarizado com 'template tags', talvez queira dar uma olhada na <a class="reference external" href="https://docs.djangoproject.com/en/dev/howto/custom-template-tags/">documentação do django</a>.</p> +<p>Vamos então criar nossa template tag 'comentarios_n_liberados'. Primeiro devemos criar uma pasta chamada templatetags, dentro da nossa app core. Dentro ta pasta vamos inicializar um pacote python e criar o arquivo comentarios_tag.py. Nele precisamos declarar nosso metodo que deve se chamar 'comentarios_n_liberados' e nele fazer uma simples consulta ao banco buscando os comentários não liberados e por fim registrar a tag apontando para o template que será renderizado. Abaixo o código mais explicado.</p> +<div class="livros"> + <div class="recomendacoes">Recomendações</div> + <a rel="noopener nofollow" href="https://www.amazon.com.br/gp/product/8575225081/ref=as_li_ss_il?ie=UTF8&linkCode=li2&tag=sipmann-20&linkId=c17fa3ac84e734741a3761e874d7d286" target="_blank"><img border="0" src="//ws-na.amazon-adsystem.com/widgets/q?_encoding=UTF8&ASIN=8575225081&Format=_SL160_&ID=AsinImage&MarketPlace=BR&ServiceVersion=20070822&WS=1&tag=sipmann-20" ></a><img src="https://ir-br.amazon-adsystem.com/e/ir?t=sipmann-20&l=li2&o=33&a=8575225081" alt="Livro Pense em Python na Amazon" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /> + <a rel="noopener nofollow" href="https://www.amazon.com.br/gp/product/B074ZTLKHB/ref=as_li_ss_il?ie=UTF8&linkCode=li2&tag=sipmann-20&linkId=e2f37c07da2dc4111ae47854b205d01a" target="_blank"><img border="0" src="//ws-na.amazon-adsystem.com/widgets/q?_encoding=UTF8&ASIN=B074ZTLKHB&Format=_SL160_&ID=AsinImage&MarketPlace=BR&ServiceVersion=20070822&WS=1&tag=sipmann-20" ></a><img src="https://ir-br.amazon-adsystem.com/e/ir?t=sipmann-20&l=li2&o=33&a=B074ZTLKHB" alt="Livro Curso Intensivo de Python na Amazon" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /> +</div><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django</span> <span class="kn">import</span> <span class="n">template</span> +<span class="kn">from</span> <span class="nn">core</span> <span class="kn">import</span> <span class="n">models</span> + +<span class="c1">#Carrega o registro de template tags</span> +<span class="n">register</span> <span class="o">=</span> <span class="n">template</span><span class="o">.</span><span class="n">Library</span><span class="p">()</span> + +<span class="c1">#Registra o metodo a seguir como uma inclusion_tag indicando o template a ser renderizad</span> +<span class="nd">@register</span><span class="o">.</span><span class="n">inclusion_tag</span><span class="p">(</span><span class="s1">&#39;comentarios_n_liberados.html&#39;</span><span class="p">)</span> +<span class="k">def</span> <span class="nf">comentarios_n_liberados</span><span class="p">():</span> + <span class="n">comentarios</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">comentario</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">liberado</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span><span class="o">.</span><span class="n">order_by</span><span class="p">(</span><span class="s1">&#39;data&#39;</span><span class="p">)[</span><span class="mi">0</span><span class="p">:</span><span class="mi">5</span><span class="p">]</span> + <span class="k">return</span> <span class="p">{</span> <span class="s1">&#39;comentarios&#39;</span> <span class="p">:</span> <span class="n">comentarios</span> <span class="p">}</span> +</pre></div> +<p>Abaixo o html do nosso template a ser renderizado, este deve estar dentro da pasta templates da nossa app core.</p> +<div class="highlight"><pre><span></span>{% if not comentarios %} + <span class="p">&lt;</span><span class="nt">p</span><span class="p">&gt;</span>Nenhum comentário novo<span class="p">&lt;/</span><span class="nt">p</span><span class="p">&gt;</span> +{% else %} + <span class="p">&lt;</span><span class="nt">ul</span><span class="p">&gt;</span> + {% for c in comentarios %} + <span class="p">&lt;</span><span class="nt">li</span> <span class="na">class</span><span class="o">=</span><span class="s">&quot;addlink&quot;</span><span class="p">&gt;</span> + <span class="p">&lt;</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">&quot;{{ c.id }}&quot;</span><span class="p">&gt;</span>{{ c.texto|truncatechars:30 }}<span class="p">&lt;/</span><span class="nt">a</span><span class="p">&gt;</span> + <span class="p">&lt;/</span><span class="nt">li</span><span class="p">&gt;</span> + {% endfor %} + <span class="p">&lt;/</span><span class="nt">ul</span><span class="p">&gt;</span> +{% endif %} +</pre></div> +<p>Com tudo isto feito, basta subir o seu servidor e ver o resultado final, que pode ser visto na imagem abaixo.</p> +<img alt="Resultado final" src="images/admin_modificado.png" /> +<p>Lembrando que aqui apenas mostrei como modificar o index do admin, para apenas listar dados do banco, mas você pode ir muito mais além. Abaixo fica a estrutura de diretórios final e um link para download do projeto funcionando.</p> +<div class="highlight"><pre><span></span>../blog/ +├── core +│ ├── templates +│ │ └── comentarios_n_liberados.html +│ ├── templatetag +│ │ └── comentarios_tag.py +│ ├── __init__.py +│ ├── admin.py +│ ├── models.py +│ ├── tests.py +│ └── views.py +├── blog +│ ├── __init__.py +│ ├── settings.py +│ ├── urls.py +│ └── wsgi.py +├── templates +│ ├── admin +│ │ └── index.html +└── manage.py +</pre></div> +<p>Espero que tenham gostado, criticas/sugestões são bem-vindas. <a class="reference external" href="https://github.com/sipmann/editando-django-admin">Fontes do Projeto</a></p> + \ No newline at end of file diff --git a/pt/feeds/all.atom.xml.gz b/pt/feeds/all.atom.xml.gz new file mode 100644 index 000000000..91aaf5cb4 Binary files /dev/null and b/pt/feeds/all.atom.xml.gz differ diff --git a/pt/feeds/azure.atom.xml b/pt/feeds/azure.atom.xml new file mode 100644 index 000000000..68e83ebf9 --- /dev/null +++ b/pt/feeds/azure.atom.xml @@ -0,0 +1,51 @@ + +Sipmann - Azurehttps://www.sipmann.com/pt/2020-10-03T19:00:00-03:00Microsoft Contra Covid2020-10-03T19:00:00-03:002020-10-03T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-03:/pt/microsoft-against-covid.html<p>Você teve seu trabalho afetado pela pandemia do covid? Bom, na última semana eu postei no <a href="https://grepora.com/2020/09/17/microsoft-ignite-certification-voucher/">Grepora</a> sobre um Voucher para certificação gratuita que a Microsoft estava distribuindo durante o evento Microsoft Ignite. Depois disto, eu fiquei sabendo que eles também estão entregando grandes discontos para quem teve o seu …</p><p>Você teve seu trabalho afetado pela pandemia do covid? Bom, na última semana eu postei no <a href="https://grepora.com/2020/09/17/microsoft-ignite-certification-voucher/">Grepora</a> sobre um Voucher para certificação gratuita que a Microsoft estava distribuindo durante o evento Microsoft Ignite. Depois disto, eu fiquei sabendo que eles também estão entregando grandes discontos para quem teve o seu trabalho afetado pela pandemia do covid. </p> +<p>Para saber se você pode receber este desconto, acesse <a href="https://docs.microsoft.com/en-us/learn/certifications/skillingoffer">https://docs.microsoft.com/en-us/learn/certifications/skillingoffer</a>.</p>Monitorando a disponibilidade de um Website com Azure Functions2020-06-22T19:00:00-03:002020-06-22T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-06-22:/pt/monitoring-website-heath-with-azure-functions.html<p>Algumas vezes você se depara com a necessidade de monitorar a disponibilidade de um website ou mudanças em seu conteúdo. É claro que temos diversas opções disponíveis no mercado, mas para fins de curiosidade, vamos programar o nosso próprio e ver o que podemos fazer. Primeiramente, tudo que você ver …</p><p>Algumas vezes você se depara com a necessidade de monitorar a disponibilidade de um website ou mudanças em seu conteúdo. É claro que temos diversas opções disponíveis no mercado, mas para fins de curiosidade, vamos programar o nosso próprio e ver o que podemos fazer. Primeiramente, tudo que você ver aqui, você pode utilizar o <a href="https://azure.microsoft.com/free/">tier gratuito</a> da Azure.</p> +<p>A ideia principal da nossa aplicação vai ser monitorar a disponibilidade do website (status code). Para criar um projeto de Azure Function, siga os passos abaixo.</p> +<p><img alt="Passos para criar um projeto Azure Functions" src="/images/azure_functions.gif"></p> +<p>Depois de criar o projeto, você vai ter alguns arquivos. Abra o arquivo principal (<code>HttpCheck.cs</code> no meu caso) e começe a programar. O arquivo principal terá uma função chamada <code>Run</code> e você pode progamar nela o seu request. Eu criei um método <code>async</code> para fazer as requisições e printar a saída diretamente no console. O código completo pode ser visto abaixo.</p> +<div class="highlight"><pre><span></span><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Linq</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Net.Http</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Threading.Tasks</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">Microsoft.Azure.WebJobs</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">Microsoft.Azure.WebJobs.Host</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">Microsoft.Extensions.Logging</span><span class="p">;</span> + +<span class="k">namespace</span> <span class="nn">Sipmann.CheckMySite</span> +<span class="p">{</span> + <span class="k">public</span> <span class="k">static</span> <span class="k">class</span> <span class="nc">HttpCheck</span> + <span class="p">{</span> + + <span class="k">private</span> <span class="k">static</span> <span class="k">async</span> <span class="n">Task</span> <span class="nf">GetTask</span><span class="p">(</span><span class="kt">string</span> <span class="n">url</span><span class="p">,</span> <span class="n">ILogger</span> <span class="n">log</span><span class="p">)</span> + <span class="p">{</span> + <span class="kt">var</span> <span class="n">request</span> <span class="p">=</span> <span class="k">new</span> <span class="n">HttpRequestMessage</span><span class="p">(</span><span class="n">HttpMethod</span><span class="p">.</span><span class="n">Get</span><span class="p">,</span> <span class="n">url</span><span class="p">);</span> + + <span class="kt">var</span> <span class="n">client</span> <span class="p">=</span> <span class="k">new</span> <span class="n">HttpClient</span><span class="p">();</span> + <span class="kt">var</span> <span class="n">response</span> <span class="p">=</span> <span class="k">await</span> <span class="n">client</span><span class="p">.</span><span class="n">SendAsync</span><span class="p">(</span><span class="n">request</span><span class="p">);</span> + + <span class="k">if</span> <span class="p">(</span><span class="n">response</span><span class="p">.</span><span class="n">IsSuccessStatusCode</span><span class="p">)</span> + <span class="p">{</span> + <span class="n">log</span><span class="p">.</span><span class="n">LogInformation</span><span class="p">(</span><span class="err">$</span><span class="s">&quot;URL ${url} esta OK&quot;</span><span class="p">);</span> + <span class="p">}</span> + <span class="k">else</span> + <span class="p">{</span> + <span class="n">log</span><span class="p">.</span><span class="n">LogInformation</span><span class="p">(</span><span class="err">$</span><span class="s">&quot;URL ${url} não esta OK&quot;</span><span class="p">);</span> + <span class="p">}</span> + <span class="p">}</span> + +<span class="na"> [FunctionName(&quot;HttpCheck&quot;)]</span> + <span class="k">public</span> <span class="k">static</span> <span class="k">void</span> <span class="nf">Run</span><span class="p">([</span><span class="n">TimerTrigger</span><span class="p">(</span><span class="s">&quot;0 */5 * * * *&quot;</span><span class="p">)]</span><span class="n">TimerInfo</span> <span class="n">myTimer</span><span class="p">,</span> <span class="n">ILogger</span> <span class="n">log</span><span class="p">)</span> + <span class="p">{</span> + <span class="c1">// URL a verificar a saúde</span> + <span class="kt">var</span> <span class="n">urls</span> <span class="p">=</span> <span class="k">new</span><span class="p">[]{</span><span class="s">&quot;https://www.sipmann.com&quot;</span><span class="p">,</span> <span class="s">&quot;https://www.canezecanez.com.br&quot;</span><span class="p">};</span> + + <span class="c1">// Starta cada request e aguarda todos de uma vez só</span> + <span class="n">Task</span><span class="p">.</span><span class="n">WaitAll</span><span class="p">(</span><span class="n">urls</span><span class="p">.</span><span class="n">Select</span><span class="p">(</span><span class="n">url</span> <span class="p">=&gt;</span> <span class="n">GetTask</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">log</span><span class="p">)).</span><span class="n">ToArray</span><span class="p">());</span> + <span class="n">log</span><span class="p">.</span><span class="n">LogInformation</span><span class="p">(</span><span class="err">$</span><span class="s">&quot;Finalizou a fila&quot;</span><span class="p">);</span> + <span class="p">}</span> + <span class="p">}</span> +<span class="p">}</span> +</code></pre></div> + +<p>Agora você pode melhorar a função e talvez enviar alguns alertas. Como por exêmplo mensagens no Telegram quando um dos sites ficar off (status code 404).</p> \ No newline at end of file diff --git a/pt/feeds/azure.atom.xml.gz b/pt/feeds/azure.atom.xml.gz new file mode 100644 index 000000000..f5741f03f Binary files /dev/null and b/pt/feeds/azure.atom.xml.gz differ diff --git a/pt/feeds/firefoxos.atom.xml b/pt/feeds/firefoxos.atom.xml new file mode 100644 index 000000000..accdef647 --- /dev/null +++ b/pt/feeds/firefoxos.atom.xml @@ -0,0 +1,42 @@ + +Sipmann - FirefoxOShttps://www.sipmann.com/pt/2014-09-02T19:00:00-03:00Desenvolvendo apps para o FirefoxOS (Parte 1)2014-09-02T19:00:00-03:002014-09-02T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2014-09-02:/pt/desenvolvendo-app-firefoxos.html<h3>Requisitos mínimos?</h3> +<p>Para seguir este tutorial você precisará do <a href="http://nodejs.org/">Nodejs</a>. Utilizaremos ele para automatizar algumas tarefas, como a criação do nosso projeto e até mesmo o empacotamento da app. Estas automatizações se darão pela utilização de algumas aplicações como o <a href="http://yeoman.io/">Yeoman</a> e o <a href="http://gruntjs.com/">Grunt</a> .</p> +<p>Também será necessário o emulador do …</p><h3>Requisitos mínimos?</h3> +<p>Para seguir este tutorial você precisará do <a href="http://nodejs.org/">Nodejs</a>. Utilizaremos ele para automatizar algumas tarefas, como a criação do nosso projeto e até mesmo o empacotamento da app. Estas automatizações se darão pela utilização de algumas aplicações como o <a href="http://yeoman.io/">Yeoman</a> e o <a href="http://gruntjs.com/">Grunt</a> .</p> +<p>Também será necessário o emulador do <a href="https://www.mozilla.org/pt-BR/firefox/os/">FirefoxOS</a>, ele roda através do seu navegador Firefox. Para instalá-lo basta ir no menu <code>Ferramentas &gt; Desenvolvedor web &gt; App Manager</code>, nesta tela basta tentar iniciar o emulador, se não possuir um já instalado, você será solicitado a fazê-lo. Neste tutorial irei utilizar a versão 1.4.</p> +<h3>Preparando o ambiente</h3> +<p>Tendo o Node instalado, vamos instalar o yeoman e o gerador de app para Firefox OS. Atenção para o parâmetro '-g' no processo de instalação, com ele os seus pacotes serão instalados globalmente, e não só para a pasta em que esta o prompt.</p> +<div class="highlight"><pre><span></span><code><span class="err">npm install -g yo</span> +<span class="err">npm install -g generator-firefoxos-app</span> +</code></pre></div> + +<p>Com ambos os pacotes acima instalados, vamos dar início a criação da app. No seu diretório de projetos ou onde desejar criar a app chama o generator instalado.</p> +<div class="highlight"><pre><span></span><code><span class="err">yo firefoxos-app</span> +</code></pre></div> + +<p>Uma vez chamado esse generator, o mesmo irá fazer alguns questionamentos, o primeiro é claro será o nome da sua aplicação, seguido da descrição e o nome do desenvolvedor.</p> +<p>Após a execução do generator, você já terá uma estrutura para desenvolvimento pronta, inclusive com um html inicial, com todas as dependências já instaladas. Vale ressaltar agora algumas tarefas disponíveis no Gruntfile.</p> +<ul> +<li>Default: Irá gerar o pacote de distribuição</li> +<li>Test: Até a presente versão do generator (0.1.3) este processo irá simplesmente rodar o validador jsHint</li> +<li>Server: Irá disponibilizar na porta 9001 um simples servidor para testar a sua app</li> +</ul> +<p>Vamos testar a nossa app. Para tal, rode o comando <code>grunt server</code> e acesse no seu navegador <code>localhost:9001</code> e devemos ver a seguinte app. Caso nenhuma página seja exibida, revise os passos ateriores e verifique se nenhum erro ocorreu.</p> +<p><img alt="App inicial" src="/images/app_inicial.png"></p> +<p>Vale ressaltar que a sua app toda estará dentro de uma pasta também chamada <code>app</code>. Nela você encontrará os seus arquivos .html, .js, .css e demais. Antes de começarmos a codificar a nossa app, vamos ver como se instala a mesma.</p> +<h3>Instalando a app</h3> +<p>Para fins de teste, não é necessário rodar o comando <code>grunt</code>, sendo que ele irá testar o JS e compactar tudo em um arquivo .zip, basta apontar a instalação para a pasta <code>app</code> dentro do seu projeto. "Mas como eu faço isto?".</p> +<p>Indo novamente na <code>App Manager</code>, clicando na lateral esquerda, onde indica "Aplicativos", teremos então disponível no inferior da tela duas opções, vamos nos ater a utilizar a primeira (<code>Adicionar aplicativo hospedado</code>).</p> +<p>Clicando nesta opção vamos navegar até a pasta da app e clicar selecionada. Pronto.</p> +<p>Simples de se instalar, não acha? O Resultado final deve ser semelhante ao abaixo.</p> +<p><img alt="App inicial" src="/images/app_visual_1.png"></p> +<h3>Acessando uma API</h3> +<p>Quando vamos programar algo mais complexo, geralmente vamos utilizar algo como, câmera, rede, lista de contatos, armazenamento e outras possibilidades. Para utilizarmos essas APIs, precisamos - assim como no desenvolvimento para android - especificar para o usuário no momento de instalação. Estes dados de acesso ficam no arquivo <code>manifes.webapp</code>, se você ainda não deu uma olhada neste arquivo, é nele que fica armazenado dados da app, como nome, descrição, versão, localização de ícones e é claro as permissões que a mesma requer.</p> +<p>As permissões ficam na propriedade permissions, na forma de <code>"chave" : True</code>. Algumas das apis são:</p> +<ul> +<li>câmera</li> +<li>contacts</li> +<li>desktop-notification</li> +<li>storage</li> +</ul> +<p>Cada permissão vai mudar o tipo de app que você esta desenvolvendo, mas aí eu sugiro ler mais na MDN <a href="https://developer.mozilla.org/en-US/Apps/Build/App_permissions">aqui</a>. Esse é o básico para iniciar no desenvolvimento de app para FirefoxOS. Na parte dois, vou começar a passar um pouco de código.</p> \ No newline at end of file diff --git a/pt/feeds/firefoxos.atom.xml.gz b/pt/feeds/firefoxos.atom.xml.gz new file mode 100644 index 000000000..956d078c7 Binary files /dev/null and b/pt/feeds/firefoxos.atom.xml.gz differ diff --git a/pt/feeds/java.atom.xml b/pt/feeds/java.atom.xml new file mode 100644 index 000000000..95b862cc7 --- /dev/null +++ b/pt/feeds/java.atom.xml @@ -0,0 +1,35 @@ + +Sipmann - Javahttps://www.sipmann.com/pt/2018-03-04T17:40:00-03:00Resolvendo java.net.SocketException: Protocol family unavailable em Java + Docker + WildFly2018-03-04T17:40:00-03:002018-03-04T17:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-03-04:/pt/socketException-protocol-family-unavailable-java-docker-wildfly.html<p>Nos últimos dias eu estou brincando com o <a class="reference external" href="http://wildfly-swarm.io/">WildFly Swarm</a> e decidi fazer o deploy de uma aplicação simples com Docker. Deveria funcionar bem, ao menos é o que pensava. Construí um container com o seguinte Dockerfile e ao invés de obter uma aplicação web, tudo que eu obtive foi …</p><p>Nos últimos dias eu estou brincando com o <a class="reference external" href="http://wildfly-swarm.io/">WildFly Swarm</a> e decidi fazer o deploy de uma aplicação simples com Docker. Deveria funcionar bem, ao menos é o que pensava. Construí um container com o seguinte Dockerfile e ao invés de obter uma aplicação web, tudo que eu obtive foi o erro <cite>java.net.SocketException: Protocol family unavailable</cite>.</p> +<div class="highlight"><pre><span></span><span class="k">FROM</span> <span class="s">java:openjdk-8-jdk</span> + +<span class="k">COPY</span> target/issues.jar /opt/issues.jar + +<span class="k">EXPOSE</span><span class="s"> 8080</span> + +<span class="k">CMD</span> <span class="p">[</span><span class="s2">&quot;java&quot;</span><span class="p">,</span><span class="s2">&quot;-jar&quot;</span><span class="p">,</span><span class="s2">&quot;/opt/issues.jar&quot;</span><span class="p">]</span> +</pre></div> +<p>Por alguma razão, WildFly e Java, ambos decidiram utilizar um protocolo IPv6 na interface de rede no Docker invés da v4, então tudo que você tem que fazer é falar ao Java que deve dar preferência em utilizar o IPv4 com a seguinte configuração no seu arquivo pom.xml dentro da tag do plugin WildFly.</p> +<div class="highlight"><pre><span></span><span class="nt">&lt;plugin&gt;</span> + <span class="nt">&lt;groupId&gt;</span>org.wildfly.swarm<span class="nt">&lt;/groupId&gt;</span> + <span class="nt">&lt;artifactId&gt;</span>wildfly-swarm-plugin<span class="nt">&lt;/artifactId&gt;</span> + <span class="nt">&lt;version&gt;</span>2018.2.0<span class="nt">&lt;/version&gt;</span> + + <span class="c">&lt;!-- ADICIONE ISTO --&gt;</span> + <span class="nt">&lt;configuration&gt;</span> + <span class="nt">&lt;mainClass&gt;</span>org.wildfly.swarm.examples.netflix.ribbon.frontend.Main<span class="nt">&lt;/mainClass&gt;</span> + <span class="nt">&lt;properties&gt;</span> + <span class="nt">&lt;java.net.preferIPv4Stack&gt;</span>true<span class="nt">&lt;/java.net.preferIPv4Stack&gt;</span> + <span class="nt">&lt;/properties&gt;</span> + <span class="nt">&lt;/configuration&gt;</span> +</pre></div> +<p>Outra forma de solucionar o problema, é adicionando a mesma propriedade ao comando de run no seu Dockerfile. Então, fica a seu critério onde adicionar. Abaixo a solução utilizando o Dockerfile.</p> +<div class="highlight"><pre><span></span><span class="k">FROM</span> <span class="s">java:openjdk-8-jdk</span> +<span class="k">ENV</span> <span class="nv">JAVA_OPTS</span><span class="o">=</span><span class="s2">&quot;-Djava.net.preferIPv4Stack=true -Djava.net.preferIPv4Addresses=true&quot;</span> + +<span class="k">COPY</span> target/issues.jar /opt/issues.jar + +<span class="k">EXPOSE</span><span class="s"> 8080</span> + +<span class="k">ENTRYPOINT</span> <span class="nb">exec</span> java <span class="nv">$JAVA_OPTS</span> -jar /opt/issues.jar +</pre></div> + \ No newline at end of file diff --git a/pt/feeds/java.atom.xml.gz b/pt/feeds/java.atom.xml.gz new file mode 100644 index 000000000..c7ceac6be Binary files /dev/null and b/pt/feeds/java.atom.xml.gz differ diff --git a/pt/feeds/linux.atom.xml b/pt/feeds/linux.atom.xml new file mode 100644 index 000000000..843fa7a7a --- /dev/null +++ b/pt/feeds/linux.atom.xml @@ -0,0 +1,68 @@ + +Sipmann - Linuxhttps://www.sipmann.com/pt/2020-10-20T19:00:00-03:00Zabbix Running on Low Memory Mode2020-10-20T19:00:00-03:002020-10-20T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-20:/pt/zabbix-running-on-low-memory-mode.html<p>Olá pessoal! Trago hoje outro post sobre Zabbix. Este é sobre aumentar o cache do seu Zabbix Server. É perfeitamente comum (se você roda com as configurações padrões) receber avisos sobre <code>Zabbix value cache running on low memory mode</code> no seu dashboard ou arquivos de log.</p> +<p><img alt="Zabbix Dashboard alertando sobre problemas de memória" src="/images/zabbix_low_memory_mode.png"> +<img alt="Zabbix Dashboard cache gráfico com 70% utilizado" src="/images/zabbix_cache_filling.png"></p> +<p>Para resolver, abra o …</p><p>Olá pessoal! Trago hoje outro post sobre Zabbix. Este é sobre aumentar o cache do seu Zabbix Server. É perfeitamente comum (se você roda com as configurações padrões) receber avisos sobre <code>Zabbix value cache running on low memory mode</code> no seu dashboard ou arquivos de log.</p> +<p><img alt="Zabbix Dashboard alertando sobre problemas de memória" src="/images/zabbix_low_memory_mode.png"> +<img alt="Zabbix Dashboard cache gráfico com 70% utilizado" src="/images/zabbix_cache_filling.png"></p> +<p>Para resolver, abra o seu arquivo de configuração (<code>zabbix_server.conf</code>) e procure pela tag <em>CacheSize</em>. Descomente a linha e defina um valor maior que 8M (8M é o valor padrão). No meu caso, nós configuramos um cache de 100M. Depois da troca, reinicie o serviço para que o mesmo tome efeito.</p> +<div class="highlight"><pre><span></span><code><span class="c1">### Option: CacheSize</span> +<span class="c1"># Size of configuration cache, in bytes.</span> +<span class="c1"># Shared memory size for storing host, item and trigger data.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 128K-64G</span> +<span class="c1"># Default:</span> +<span class="na">CacheSize</span><span class="o">=</span><span class="s">100M #Descomente esta linha</span> +</code></pre></div> + +<p><img alt="Zabbix Dashboard resolved memory problem" src="/images/zabbix_low_memory_solved.png"></p> +<p>Até breve.</p>Zabbix poller processes more than 75%2020-07-02T19:00:00-03:002020-07-02T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-07-02:/pt/zabbix-poller-processes-more-than-75.html<p>Este é o terceiro post sobre configurações para o Zabbix. Todas as alterações que eu sugiro nestes posts, são baseadas em um servidor com 50+ hosts. Outro problema que pode ocorrer em seu servidor, é o poller de informações ficar sobrecarregado pela quantidade de servidores que ele precisa pegar carga …</p><p>Este é o terceiro post sobre configurações para o Zabbix. Todas as alterações que eu sugiro nestes posts, são baseadas em um servidor com 50+ hosts. Outro problema que pode ocorrer em seu servidor, é o poller de informações ficar sobrecarregado pela quantidade de servidores que ele precisa pegar carga de informações juntamente com os servidores que não respondem a requisição. Abaixo duas imagens onde você pode ver o log e um gráfico onde aparecem os percentuais de uso dos poller. </p> +<p><img alt="Dashboard log sobre o processo do poller" src="/images/zabbix_pooler.png"></p> +<p><img alt="Gráfico mostrando o percentual de utilização de cada coletor" src="/images/zabbix_pooler_3.png"></p> +<p>Para resolver o problema acima, vamos voltar ao arquivo de configuração <code>zabbix_server.conf</code> e localizar duas variáveis, <code>StartPollers</code> e <code>StartPollersUnreachable</code>. Aumente o valor delas conforme necessário. Não existe um número mágico, você deve verificar o que melhor funciona para você. Mas tenha em mente que <code>StartPollersUnreachable</code> é responsável por aqueles hosts que não respondem ou não são localizados e irão segurar a thread do poller por mais tempo, causando uma fila e um maior processamento/tempo de atualização.</p> +<div class="highlight"><pre><span></span><code><span class="c1">### Option: StartPollers</span> +<span class="c1"># Number of pre-forked instances of pollers.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 0-1000</span> +<span class="c1"># Default:</span> +<span class="na">StartPollers</span><span class="o">=</span><span class="s">20</span> + +<span class="c1">#...</span> + +<span class="c1">### Option: StartPollersUnreachable</span> +<span class="c1"># Number of pre-forked instances of pollers for unreachable hosts (including IPMI and Java).</span> +<span class="c1"># At least one poller for unreachable hosts must be running if regular, IPMI or Java pollers</span> +<span class="c1"># are started.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 0-1000</span> +<span class="c1"># Default:</span> +<span class="na">StartPollersUnreachable</span><span class="o">=</span><span class="s">5</span> +</code></pre></div> + +<p>Depois da alteração, reinicie o serviço e espere alguns momentos e veja o seu dashboard novamente. Abaixo o efeito que a troca teve em um dos servidores que acompanho.</p> +<p><img alt="Gráfico mostrando os novos percentuais de utilização dos processos após as alterações" src="/images/zabbix_pooler_4.png"></p>Zabbix ICMP pinger processes more than 75%2020-05-25T16:00:00-03:002020-05-25T16:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-05-25:/pt/zabbix-icmp-pinger-processes-more-than-75.html<p>Então o seu systema de monitoramento creasceu e o seu Zabbix começou a printar "<em>Zabbix icmp pinger processes more than 75% busy</em>" no seu dashboard.</p> +<p><img alt="Dashboard do zabbix avisando sobre o erro" src="/images/zabbix_pinger01.png"></p> +<p>Tudo que você tem a fazer é abrir o seu arquivo de configuração (<code>/etc/zabbix/zabbix_server.conf</code>) e localizar a tag chamada <code>StartPingers</code>. Ela deve …</p><p>Então o seu systema de monitoramento creasceu e o seu Zabbix começou a printar "<em>Zabbix icmp pinger processes more than 75% busy</em>" no seu dashboard.</p> +<p><img alt="Dashboard do zabbix avisando sobre o erro" src="/images/zabbix_pinger01.png"></p> +<p>Tudo que você tem a fazer é abrir o seu arquivo de configuração (<code>/etc/zabbix/zabbix_server.conf</code>) e localizar a tag chamada <code>StartPingers</code>. Ela deve estar comentáda por padrão. Descomente a lina e define o seu valor para algo como 3 or 4. Deve resolver seu problema, ao menos até um próximo crescimento do seu monitoramento.</p> +<div class="highlight"><pre><span></span><code><span class="c1">### Option: StartPingers</span> +<span class="c1"># Number of pre-forked instances of ICMP pingers.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 0-1000</span> +<span class="c1"># Default:</span> +<span class="nv">StartPingers</span><span class="o">=</span><span class="m">4</span> +</code></pre></div>Zabbix Server Out of Memory2020-02-27T19:00:00-03:002020-02-27T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-02-27:/pt/zabbix-server-out-of-memory-crash.html<p>Você tem um servidor Zabbix crashando e observando o arquivo de log <code>/var/log/zabbix/zabbix_server.log</code> você localiza a seguinte mensagem referênciando falta de memória?</p> +<div class="highlight"><pre><span></span><code>__mem_malloc: skipped <span class="m">0</span> asked <span class="m">24</span> skip_min <span class="m">18446744073709551615</span> skip_max <span class="m">0</span> +<span class="o">[</span>file:dbconfig.c,line:94<span class="o">]</span> __zbx_mem_realloc<span class="o">()</span>: out of memory <span class="o">(</span>requested <span class="m">16</span> bytes<span class="o">)</span> +<span class="o">[</span>file:dbconfig.c …</code></pre></div><p>Você tem um servidor Zabbix crashando e observando o arquivo de log <code>/var/log/zabbix/zabbix_server.log</code> você localiza a seguinte mensagem referênciando falta de memória?</p> +<div class="highlight"><pre><span></span><code>__mem_malloc: skipped <span class="m">0</span> asked <span class="m">24</span> skip_min <span class="m">18446744073709551615</span> skip_max <span class="m">0</span> +<span class="o">[</span>file:dbconfig.c,line:94<span class="o">]</span> __zbx_mem_realloc<span class="o">()</span>: out of memory <span class="o">(</span>requested <span class="m">16</span> bytes<span class="o">)</span> +<span class="o">[</span>file:dbconfig.c,line:94<span class="o">]</span> __zbx_mem_realloc<span class="o">()</span>: please increase CacheSize configuration parameter +</code></pre></div> + +<p>Apesar da simples solução para o erro, isso acaba sendo um problema comum em servidores que tem uma certa quantidade de itens sendo monitorados (servidores, switches, firewalls, bancos, etc...). Para resolver o problema, vá até o ser arquivo <code>zabbix_server.conf</code> e procure pela propriedade <code>CacheSize</code> e sete o seu valor para uma quantidade maior. O seu valor default deve ser algo como 8M. Em clientes que tenham algo como 4 servidores, 7 firewalls/appliances, e algumas outras coisas (bancos, apps), 32M deve resolver o problema, mas você pode setar até algo como 8G (ressalto que mais memória nem sempre é melhor).</p> +<p>Até breve.</p> \ No newline at end of file diff --git a/pt/feeds/linux.atom.xml.gz b/pt/feeds/linux.atom.xml.gz new file mode 100644 index 000000000..d51d9f63d Binary files /dev/null and b/pt/feeds/linux.atom.xml.gz differ diff --git a/pt/feeds/mauricio-camargo-sipmann.atom.xml b/pt/feeds/mauricio-camargo-sipmann.atom.xml new file mode 100644 index 000000000..183dab218 --- /dev/null +++ b/pt/feeds/mauricio-camargo-sipmann.atom.xml @@ -0,0 +1,829 @@ + +Sipmann - Maurício Camargo Sipmannhttps://www.sipmann.com/pt/2020-12-21T13:30:00-03:00Monitorando restarts do MySQL com PowerShell2020-12-21T13:30:00-03:002020-12-21T13:30:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-12-21:/pt/monitoring-mysql-restarts-with-powershell.html<p>Bom, chegou a hora para mais um script PowerShell. Se você ainda não viu os outros, de uma olhada no link abaixo.</p> +<ul> +<li><a href="https://www.sipmann.com/pt/monitoring-mysql-replication-with-powershell.html">Monitorando status de replicação do MySQL com PowerShell</a></li> +</ul> +<p>Este aqui é um script bem simples, mas novamente, se seu cliente não possui um servidor Zabbix ou não permite …</p><p>Bom, chegou a hora para mais um script PowerShell. Se você ainda não viu os outros, de uma olhada no link abaixo.</p> +<ul> +<li><a href="https://www.sipmann.com/pt/monitoring-mysql-replication-with-powershell.html">Monitorando status de replicação do MySQL com PowerShell</a></li> +</ul> +<p>Este aqui é um script bem simples, mas novamente, se seu cliente não possui um servidor Zabbix ou não permite que você configure um para realizar este monitoramento, um conjunto de scripts pode ser bem útil. Primeiramente nós executamos uma query báscia <code>SHOW GLOBAL STATUS LIKE 'Uptime'</code>, com ela nós conseguimos capturar exatamente o que nós estamos procurando.</p> +<p>Se por alguma razão o comando falhar (verificamos atravez da variábel global <code>$lastExitCode</code>), nós mandamos um e-mail lhe avisando sobre o problema ocorrido.</p> +<p>E então, nós chegamos à parte onde fazemos o parse do valor obtido, esta parte é bem similar ao parse que codificamos no primeiro post sobre monitoramento utilizando PowerShell. Nós basicamentes procuramos pela linha contendo <code>Value</code>, separamos por espaço e então parseamos a segunda posição em um inteiro. Então tudo que precisamos fazer é verificar se o valor parseado é menor que o nosso threshold, se for menor, nós mandamos um e-mail.</p> +<div class="highlight"><pre><span></span><code><span class="nv">$MailFrom</span> <span class="p">=</span> <span class="s1">&#39;maurio[at]sipmann.com&#39;</span> +<span class="nv">$MailTo</span> <span class="p">=</span> <span class="s1">&#39;mauricio[at]sipmann.com&#39;</span> +<span class="nv">$MysqlHost</span> <span class="p">=</span> <span class="s1">&#39;127.0.0.1&#39;</span> +<span class="nv">$MysqlUser</span> <span class="p">=</span> <span class="s1">&#39;root&#39;</span> +<span class="nv">$MysqlPass</span> <span class="p">=</span> <span class="s1">&#39;123&#39;</span> + + +<span class="nv">$data</span> <span class="p">=</span> <span class="p">$(</span><span class="n">mysql</span> <span class="n">-h</span> <span class="nv">$MysqlHost</span> <span class="n">-u</span> <span class="nv">$MysqlUser</span> <span class="n">-p</span><span class="s2">&quot;$MysqlPass&quot;</span> <span class="n">-e</span> <span class="s2">&quot;SHOW GLOBAL STATUS LIKE &#39;Uptime&#39; \G&quot;</span><span class="p">)</span> + +<span class="cm">&lt;# Unable to execute the sql Command #&gt;</span> +<span class="k">if</span> <span class="p">(</span><span class="nv">$lastExitCode</span> <span class="o">-eq</span> <span class="n">1</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Send-MailMessage</span> <span class="n">-To</span> <span class="nv">$MailTo</span> <span class="n">-From</span> <span class="nv">$MailFrom</span> <span class="n">-Subject</span> <span class="s1">&#39;Connection problem&#39;</span> <span class="n">-bodyAsHtml</span> <span class="s2">&quot;Connection problem on host ${MysqlHost}&quot;</span> <span class="n">-Credential</span> <span class="nb">Get-Credential</span> <span class="n">-SmtpServer</span> <span class="s1">&#39;smtp.office365.com&#39;</span> <span class="n">-Port</span> <span class="n">587</span> <span class="n">-UseSsl</span> + <span class="n">exit</span> +<span class="p">}</span> + +<span class="nv">$UpTime</span> <span class="p">=</span> <span class="no">[int]</span><span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Value:&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> + +<span class="cm">&lt;# If the uptime is lower then 20 minutes #&gt;</span> +<span class="k">if</span> <span class="p">(</span><span class="nv">$UpTime</span> <span class="o">-lt</span> <span class="n">1200</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Send-MailMessage</span> <span class="n">-To</span> <span class="nv">$MailTo</span> <span class="n">-From</span> <span class="nv">$MailFrom</span> <span class="n">-Subject</span> <span class="s2">&quot;MySQL Restarted&quot;</span> <span class="n">-bodyAsHtml</span> <span class="s2">&quot;MySQL host ${MysqlHost} restarted less than 20 minutes ago&quot;</span> <span class="n">-Credential</span> <span class="nb">Get-Credential</span> <span class="n">-SmtpServer</span> <span class="s1">&#39;smtp.office365.com&#39;</span> <span class="n">-Port</span> <span class="n">587</span> <span class="n">-UseSsl</span> +<span class="p">}</span> +</code></pre></div> + +<p>Este script (e os outros que eu utilizo) estão disponíveis no meu GitHub <a href="https://github.com/sipmann/PowerShellScripts">aqui</a>. Tenha em mente que os scripts localizados no GitHub, são um pouco diferentes do que exibido aqui. Espero que tenha achado útil.</p>Trocando a senha de um usuário do MySQL sem downtime da aplicação2020-12-09T13:40:00-03:002020-12-09T13:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-12-09:/pt/mysql-dual-password-functionality.html<p>Você deseja trocar a senha de um usuário do MySQL que está sendo utilizado por uma aplicação e não sofrer nenhum downtime? Bom, a versão 8.0.14 do MySQL foi liberada com uma feature chamada <a href="https://dev.mysql.com/doc/refman/8.0/en/password-management.html#dual-passwords">Dual Password Support</a>, com esta feature você pode alterar a senha de um usuário …</p><p>Você deseja trocar a senha de um usuário do MySQL que está sendo utilizado por uma aplicação e não sofrer nenhum downtime? Bom, a versão 8.0.14 do MySQL foi liberada com uma feature chamada <a href="https://dev.mysql.com/doc/refman/8.0/en/password-management.html#dual-passwords">Dual Password Support</a>, com esta feature você pode alterar a senha de um usuário mantendo a anterior ainda funcionando como uma forma de "backup". Desta forma, você ainda conseguirá autenticar com o usuário utilizando tanto a nova senha, quanto a anterior. Com isto, o seu processo de troca de senha fica algo como:</p> +<p>1) Troque a senha mantendo a anterior;</p> +<p>2) Faça o Deploy da nova configuração na sua aplicação/cluster;</p> +<p>3) Descarte a senha anterior.</p> +<p>Para alterar a senha mantendo a anterior, você deve rodar o seguinte comando:</p> +<div class="highlight"><pre><span></span><code><span class="k">ALTER</span> <span class="n">USER</span> <span class="s1">&#39;appuser&#39;</span><span class="o">@</span><span class="s1">&#39;localhost&#39;</span> <span class="n">IDENTIFIED</span> <span class="k">BY</span> <span class="s1">&#39;new_password&#39;</span> <span class="n">RETAIN</span> <span class="n">CURRENT</span> <span class="n">PASSWORD</span><span class="p">;</span> +</code></pre></div> + +<p>Para descartar a senha antiga, rode o seguinte:</p> +<div class="highlight"><pre><span></span><code><span class="k">ALTER</span> <span class="n">USER</span> <span class="s1">&#39;appuser&#39;</span><span class="o">@</span><span class="s1">&#39;localhost&#39;</span> <span class="n">DISCARD</span> <span class="n">OLD</span> <span class="n">PASSWORD</span><span class="p">;</span> +</code></pre></div> + +<p>E pronto. Espero que isto lhe ajude a evitar downtimes e dores de cabeça :)</p>Apache Nifi JSON to SQL removendo underline2020-12-02T14:00:00-03:002020-12-02T14:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-12-02:/pt/apache-nifi-json-to-sql-replacing-underscore.html<p>Recentemente eu estava desenvolvendo alguns processos de ETL com o Apache NiFi. Mas após alguns minutos desenhando o meu fluxo, eu vi um comportamento estranho do componente ConvertJSONToSQL, que estava substituindo os underline ('_') do nome de um campo utilizado na condição da SQL (eu estava preparando um UPDATE). Aquilo …</p><p>Recentemente eu estava desenvolvendo alguns processos de ETL com o Apache NiFi. Mas após alguns minutos desenhando o meu fluxo, eu vi um comportamento estranho do componente ConvertJSONToSQL, que estava substituindo os underline ('_') do nome de um campo utilizado na condição da SQL (eu estava preparando um UPDATE). Aquilo estava estranho, uma vez que na definição do SET da SQL, o nome do campo permanecia inalterado. Depois de algumas pesquisas, achei uma doc que a propriedade (veja abaixo) <code>Translate Field Names</code> era a responsável por este comportamento estranho.</p> +<p><img alt="Apache NiFi JSONToSQL config" src="/images/apache_nifi_jsontosql.png"></p> +<p>Antes de definir a propriedade como <strong>FALSE</strong>, esteja ciente que as propriedades do seu JSON devem ser exatamente iguais aos nomes dos campos da sua tabela.</p>Bloqueando um usuário do SQL Server baseado em uma tabela de horários2020-11-14T07:00:00-03:002020-11-14T07:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-11-14:/pt/blocking-user-on-sql-server-based-on-schedule.html<p>Ok, algum tempo atrás, eu postei sobre como você pode impor limites às conexões do SQL Server utilizando o <a href="https://www.sipmann.com/limiting-connection-resources-sql-server.html#.X6Cz8IhKhPY">Resource Governor</a>. Mas, e se você não pode utilizar ele? Você sempre pode bloquear logins usando uma trigger, mas eu não gosto da ideia de ter um select rodando a cada …</p><p>Ok, algum tempo atrás, eu postei sobre como você pode impor limites às conexões do SQL Server utilizando o <a href="https://www.sipmann.com/limiting-connection-resources-sql-server.html#.X6Cz8IhKhPY">Resource Governor</a>. Mas, e se você não pode utilizar ele? Você sempre pode bloquear logins usando uma trigger, mas eu não gosto da ideia de ter um select rodando a cada login. Então, eu cheguei a esta solução, utilizando uma stored procedure, uma tabela e o Agent.</p> +<p>A ideia principal é armazenar o horário em que um usuário deve ser bloqueado pelo Agent. Abaixo você pode ver a criação da tabela:</p> +<div class="highlight"><pre><span></span><code><span class="k">CREATE</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"> </span><span class="p">(</span><span class="w"></span> +<span class="w"> </span><span class="n">Id</span><span class="w"> </span><span class="nc">INT</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">LoginName</span><span class="w"> </span><span class="nc">NVARCHAR</span><span class="p">(</span><span class="mi">100</span><span class="p">)</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">HrInicio</span><span class="w"> </span><span class="nc">TIME</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"> </span><span class="cm">/* horário de inicio do bloqueio */</span><span class="w"></span> +<span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="nc">TIME</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"> </span><span class="cm">/*horário de termino */</span><span class="w"></span> +<span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="nc">INT</span><span class="w"> </span><span class="k">DEFAULT</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="cm">/* 0 = desbloqueado, 1 = bloqueado */</span><span class="w"></span> +<span class="w"> </span><span class="k">PRIMARY</span><span class="w"> </span><span class="k">KEY</span><span class="w"> </span><span class="p">(</span><span class="n">Id</span><span class="p">)</span><span class="w"></span> +<span class="p">);</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> + +<span class="cm">/* regra para Não bloquear o usuário SA */</span><span class="w"></span> +<span class="k">ALTER</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"></span> +<span class="w"> </span><span class="k">ADD</span><span class="w"> </span><span class="k">CONSTRAINT</span><span class="w"> </span><span class="n">chk_users</span><span class="w"> </span><span class="k">CHECK</span><span class="w"> </span><span class="p">(</span><span class="n">LoginName</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;sa&#39;</span><span class="p">));</span><span class="w"></span> + +<span class="k">ALTER</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"></span> +<span class="w"> </span><span class="k">ADD</span><span class="w"> </span><span class="k">CONSTRAINT</span><span class="w"> </span><span class="n">chk_hora_final_maior</span><span class="w"> </span><span class="k">CHECK</span><span class="w"> </span><span class="p">(</span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="n">HrInicio</span><span class="p">);</span><span class="w"></span> + +<span class="k">ALTER</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"></span> +<span class="w"> </span><span class="k">ADD</span><span class="w"> </span><span class="k">CONSTRAINT</span><span class="w"> </span><span class="n">chk_status_bloqueio</span><span class="w"> </span><span class="k">CHECK</span><span class="w"> </span><span class="p">(</span><span class="n">Bloqueado</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">));</span><span class="w"></span> + +<span class="k">CREATE</span><span class="w"> </span><span class="k">SEQUENCE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">seq_HorariosBloqueio</span><span class="w"> </span><span class="k">START</span><span class="w"> </span><span class="k">WITH</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="n">INCREMENT</span><span class="w"> </span><span class="k">BY</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +</code></pre></div> + +<p>Depois de criar a tabela, vamos verificar a procedure que vai fazer todo o trabalho de habilitar/desabilitar os usuários. Fique ciente que, nesta procedure, eu defini o nome do banco onde a tabela está armazenada. Você pode substituir o nome <code>DBATOOLS</code> pelo o nome da sua base.</p> +<div class="highlight"><pre><span></span><code><span class="k">IF</span><span class="w"> </span><span class="nf">OBJECT_ID</span><span class="p">(</span><span class="s1">&#39;dbo.sp_ValidarLogin&#39;</span><span class="p">)</span><span class="w"> </span><span class="k">IS</span><span class="w"> </span><span class="k">NULL</span><span class="w"></span> +<span class="w"> </span><span class="k">EXEC</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;CREATE PROCEDURE dbo.sp_ValidarLogin AS RETURN 0;&#39;</span><span class="p">);</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> + +<span class="k">CREATE</span><span class="w"> </span><span class="ow">OR</span><span class="w"> </span><span class="k">ALTER</span><span class="w"> </span><span class="k">PROC</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">sp_ValidarLogin</span><span class="w"></span> +<span class="k">AS</span><span class="w"> </span><span class="k">BEGIN</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="nc">NVARCHAR</span><span class="p">(</span><span class="mi">100</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="nc">TIME</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="k">SET</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nf">CAST</span><span class="p">(</span><span class="nf">GETDATE</span><span class="p">()</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="nc">TIME</span><span class="p">);</span><span class="w"></span> + +<span class="w"> </span><span class="cm">/* Bloqueia os que ainda não estiverem bloqueados de acordo com a hora atual */</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="n">block_cursor</span><span class="w"> </span><span class="nc">CURSOR</span><span class="w"></span> +<span class="w"> </span><span class="k">FOR</span><span class="w"> </span><span class="k">SELECT</span><span class="w"> </span><span class="n">LoginName</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&lt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&gt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"></span> +<span class="w"> </span><span class="k">OPEN</span><span class="w"> </span><span class="n">block_cursor</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">block_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> + +<span class="w"> </span><span class="k">WHILE</span><span class="w"> </span><span class="nb">@@FETCH_STATUS</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"></span> +<span class="w"> </span><span class="k">BEGIN</span><span class="w"></span> +<span class="w"> </span><span class="k">exec</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;ALTER LOGIN &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="s1">&#39; DISABLE;&#39;</span><span class="p">);</span><span class="w"></span> + +<span class="w"> </span><span class="k">print</span><span class="w"> </span><span class="s1">&#39;Bloqued usuario &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">block_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> +<span class="w"> </span><span class="k">END</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">CLOSE</span><span class="w"> </span><span class="n">block_cursor</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="k">DEALLOCATE</span><span class="w"> </span><span class="n">block_cursor</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">UPDATE</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">SET</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&lt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&gt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"></span> + + +<span class="w"> </span><span class="cm">/* Libera quem estava bloqueado */</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="nc">CURSOR</span><span class="w"></span> +<span class="w"> </span><span class="k">FOR</span><span class="w"> </span><span class="k">SELECT</span><span class="w"> </span><span class="n">LoginName</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="p">(</span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">OR</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="p">)</span><span class="w"></span> +<span class="w"> </span><span class="k">OPEN</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> + +<span class="w"> </span><span class="k">WHILE</span><span class="w"> </span><span class="nb">@@FETCH_STATUS</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"></span> +<span class="w"> </span><span class="k">BEGIN</span><span class="w"></span> +<span class="w"> </span><span class="k">exec</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;ALTER LOGIN &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"> </span><span class="o">+</span><span class="s1">&#39; ENABLE;&#39;</span><span class="p">);</span><span class="w"></span> + +<span class="w"> </span><span class="k">print</span><span class="w"> </span><span class="s1">&#39;Unbloqued usuario &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> +<span class="w"> </span><span class="k">END</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">CLOSE</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="k">DEALLOCATE</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">UPDATE</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">SET</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="p">(</span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">OR</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="p">)</span><span class="w"></span> +<span class="k">END</span><span class="p">;</span><span class="w"></span> +</code></pre></div> + +<p>Certo, então agora tudo que temos que fazer é definir o job no Agent para rodar a procedure de minuto em minuto. Novamente, a ideia principal é chamar a procedure quando um usuário deve ser bloqueado e quando deve ser desbloqueado.</p> +<div class="highlight"><pre><span></span><code><span class="err"> -- Vai bloquear o usuário protheus das 10 AM até 15 PM</span> +<span class="err"> INSERT INTO dbo.HorariosBloqueio (Id, LoginName, HrInicio, HrTermino) VALUES (NEXT VALUE FOR seq_HorariosBloqueio, &#39;protheus&#39;, &#39;10:00:00&#39;, &#39;15:00:00&#39;);</span> +</code></pre></div>Como definir as colunas no select utilizando Entity Framework2020-10-28T19:00:00-03:002020-10-28T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-28:/pt/select_specific_fields_with_efcore.html<p>Então, você utiliza Entity Framework Core e geralmente faz o seu selecto da seguinte forma, talvez você está retornando muitos dados.</p> +<div class="highlight"><pre><span></span><code><span class="kt">var</span> <span class="n">products</span> <span class="p">=</span> <span class="n">Products</span> + <span class="p">.</span><span class="n">Where</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span> <span class="p">&gt;</span> <span class="m">0</span><span class="p">)</span> + <span class="p">.</span><span class="n">OrderBy</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">)</span> + <span class="p">.</span><span class="n">ToList</span><span class="p">()</span> +</code></pre></div> + +<p>Rodando a query acima, em uma base de testes você obtem o seguinte resultado, veja quantas …</p><p>Então, você utiliza Entity Framework Core e geralmente faz o seu selecto da seguinte forma, talvez você está retornando muitos dados.</p> +<div class="highlight"><pre><span></span><code><span class="kt">var</span> <span class="n">products</span> <span class="p">=</span> <span class="n">Products</span> + <span class="p">.</span><span class="n">Where</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span> <span class="p">&gt;</span> <span class="m">0</span><span class="p">)</span> + <span class="p">.</span><span class="n">OrderBy</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">)</span> + <span class="p">.</span><span class="n">ToList</span><span class="p">()</span> +</code></pre></div> + +<p>Rodando a query acima, em uma base de testes você obtem o seguinte resultado, veja quantas colunas estão retornando da sua base de dados.</p> +<p><img alt="Print com todas as colunas" src="/images/ef_core_allcolumns.png"></p> +<p>No meu caso, eu só pretendo ter de volta as colunas Title, PublishedData e uma pequena descrição. Então para selecionar apenas estes campos, nós temos algumas opções. Na primeira, nós vamos definir os campos e retornar um objeto do tipo Dynamic. A segunda forma, é dar ao .NET o objeto a ser retornado, pode ser por exêmplo um DTO.</p> +<div class="highlight"><pre><span></span><code><span class="kt">var</span> <span class="n">products</span> <span class="p">=</span> <span class="n">Products</span> + + <span class="p">.</span><span class="n">Select</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="k">new</span> <span class="p">{</span><span class="n">p</span><span class="p">.</span><span class="n">ProductID</span><span class="p">,</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">,</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span><span class="p">,</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitPrice</span><span class="p">})</span> + <span class="c1">//.Select(p =&gt; new ProductDTO {p.ProductID, p.ProductName, p.UnitsInStock, p.UnitPrice})</span> + + <span class="p">.</span><span class="n">Where</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span> <span class="p">&gt;</span> <span class="m">0</span><span class="p">)</span> + <span class="p">.</span><span class="n">OrderBy</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">)</span> + <span class="p">.</span><span class="n">ToList</span><span class="p">()</span> +</code></pre></div> + +<p><img alt="Print com menos colunas e também menor quantidade de dados" src="/images/ef_core_less_columns.png"></p>Zabbix Running on Low Memory Mode2020-10-20T19:00:00-03:002020-10-20T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-20:/pt/zabbix-running-on-low-memory-mode.html<p>Olá pessoal! Trago hoje outro post sobre Zabbix. Este é sobre aumentar o cache do seu Zabbix Server. É perfeitamente comum (se você roda com as configurações padrões) receber avisos sobre <code>Zabbix value cache running on low memory mode</code> no seu dashboard ou arquivos de log.</p> +<p><img alt="Zabbix Dashboard alertando sobre problemas de memória" src="/images/zabbix_low_memory_mode.png"> +<img alt="Zabbix Dashboard cache gráfico com 70% utilizado" src="/images/zabbix_cache_filling.png"></p> +<p>Para resolver, abra o …</p><p>Olá pessoal! Trago hoje outro post sobre Zabbix. Este é sobre aumentar o cache do seu Zabbix Server. É perfeitamente comum (se você roda com as configurações padrões) receber avisos sobre <code>Zabbix value cache running on low memory mode</code> no seu dashboard ou arquivos de log.</p> +<p><img alt="Zabbix Dashboard alertando sobre problemas de memória" src="/images/zabbix_low_memory_mode.png"> +<img alt="Zabbix Dashboard cache gráfico com 70% utilizado" src="/images/zabbix_cache_filling.png"></p> +<p>Para resolver, abra o seu arquivo de configuração (<code>zabbix_server.conf</code>) e procure pela tag <em>CacheSize</em>. Descomente a linha e defina um valor maior que 8M (8M é o valor padrão). No meu caso, nós configuramos um cache de 100M. Depois da troca, reinicie o serviço para que o mesmo tome efeito.</p> +<div class="highlight"><pre><span></span><code><span class="c1">### Option: CacheSize</span> +<span class="c1"># Size of configuration cache, in bytes.</span> +<span class="c1"># Shared memory size for storing host, item and trigger data.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 128K-64G</span> +<span class="c1"># Default:</span> +<span class="na">CacheSize</span><span class="o">=</span><span class="s">100M #Descomente esta linha</span> +</code></pre></div> + +<p><img alt="Zabbix Dashboard resolved memory problem" src="/images/zabbix_low_memory_solved.png"></p> +<p>Até breve.</p>Monitorando status de replicação do MySQL com PowerShell2020-10-14T19:00:00-03:002020-10-14T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-14:/pt/monitoring-mysql-replication-with-powershell.html<p>Tenho migrado alguns scripts bash que tenho para PowerShell, e chegou a vez de migrar um script de monitoramento de replicação do MySQL. Fica como crédito o script original do <a href="https://handyman.dulare.com/mysql-replication-status-alerts-with-bash-script/">Paweł</a>. É um script bem simples onde eu verifico algumas tags resultantes do <code>SHOW SLAVE STATUS\G</code>, são elas. <code>Slave_IO_Running …</code></p><p>Tenho migrado alguns scripts bash que tenho para PowerShell, e chegou a vez de migrar um script de monitoramento de replicação do MySQL. Fica como crédito o script original do <a href="https://handyman.dulare.com/mysql-replication-status-alerts-with-bash-script/">Paweł</a>. É um script bem simples onde eu verifico algumas tags resultantes do <code>SHOW SLAVE STATUS\G</code>, são elas. <code>Slave_IO_Running</code>, <code>Slave_SQL_Running</code> e <code>Seconds_Behind_Master</code>. Ainda preciso verificar formas mais corretas de armazenar/carregar as variáveis como usuários e senha, se tiver alguma dica, fique à vontade para inclusive fazer um pull request (<a href="https://github.com/sipmann/PowerShellScripts">aqui</a>) no repositório onde vou armazenar alguns dos meus scripts.</p> +<div class="highlight"><pre><span></span><code><span class="cm">&lt;#</span> +<span class="cm"> Variables definition</span> +<span class="cm">#&gt;</span> +<span class="nv">$MaxSeconds</span> <span class="p">=</span> <span class="n">120</span> <span class="c"># Max seconds behind master allowed</span> +<span class="nv">$MysqlUser</span> <span class="p">=</span> <span class="s1">&#39;root&#39;</span> +<span class="nv">$MysqlPass</span> <span class="p">=</span> <span class="s1">&#39;&#39;</span> + +<span class="nv">$MailTo</span> <span class="p">=</span> <span class="s1">&#39;mauricio@sipmann.com&#39;</span> +<span class="nv">$MailFrom</span> <span class="p">=</span> <span class="s1">&#39;mauricio@sipmann.com&#39;</span> + + +<span class="nv">$data</span> <span class="p">=</span> <span class="p">$(</span><span class="n">mysql</span> <span class="n">-u</span> <span class="nv">$MysqlUser</span> <span class="n">-p</span><span class="s2">&quot;$MysqlPass&quot;</span> <span class="n">-e</span> <span class="s1">&#39;SHOW SLAVE STATUS \G&#39;</span><span class="p">)</span> + +<span class="c">#Debug data</span> +<span class="c">#$data = Get-Content &#39;c:\temp\sampleresult.txt&#39;</span> + +<span class="cm">&lt;# Parse the data #&gt;</span> +<span class="nv">$IORunning</span> <span class="p">=</span> <span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Slave_IO_Running:&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> +<span class="nv">$SQLRunning</span> <span class="p">=</span> <span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Slave_SQL_Running:&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> +<span class="nv">$LastErrNo</span> <span class="p">=</span> <span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Last_Errno&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> +<span class="nv">$SecondsBh</span> <span class="p">=</span> <span class="no">[int]</span><span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Seconds_Behind_Master&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> + +<span class="k">If</span> <span class="p">(</span><span class="nv">$IORunning</span> <span class="o">-Eq</span> <span class="s1">&#39;No&#39;</span> <span class="o">-Or</span> <span class="nv">$SQLRunning</span> <span class="o">-Eq</span> <span class="s1">&#39;No&#39;</span> <span class="o">-Or</span> <span class="nv">$SecondsBh</span> <span class="o">-gt</span> <span class="nv">$MaxSeconds</span><span class="p">)</span> <span class="p">{</span> + <span class="nv">$MailBody</span> <span class="p">=</span> <span class="s1">&#39;&lt;h1&gt;Problema na replicação&lt;/h1&gt;&lt;br&gt;&#39;</span> + + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39; IO Running: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$IORunning</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39; SQL Running: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$SQLRunning</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39;Seconds Behind: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$SecondsBh</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39; Last Err No: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$LastErrNo</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + + <span class="cm">&lt;# Send e-mail, maybe some telegram message here too #&gt;</span> + <span class="nb">Send-MailMessage</span> <span class="n">-To</span> <span class="nv">$MailTo</span> <span class="n">-From</span> <span class="nv">$MailFrom</span> <span class="n">-Subject</span> <span class="s1">&#39;Problemas na replicação&#39;</span> <span class="n">-bodyAsHtml</span> <span class="nv">$MailBody</span> <span class="n">-Credential</span> <span class="p">(</span><span class="nb">Get-Credential</span><span class="p">)</span> <span class="n">-SmtpServer</span> <span class="s1">&#39;smtp.office365.com&#39;</span> <span class="n">-Port</span> <span class="n">587</span> <span class="n">-UseSsl</span> +<span class="p">}</span> <span class="k">Else</span> <span class="p">{</span> + <span class="nb">Write-Host</span> <span class="s2">&quot;Up and running&quot;</span> +<span class="p">}</span> +</code></pre></div>Microsoft Contra Covid2020-10-03T19:00:00-03:002020-10-03T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-03:/pt/microsoft-against-covid.html<p>Você teve seu trabalho afetado pela pandemia do covid? Bom, na última semana eu postei no <a href="https://grepora.com/2020/09/17/microsoft-ignite-certification-voucher/">Grepora</a> sobre um Voucher para certificação gratuita que a Microsoft estava distribuindo durante o evento Microsoft Ignite. Depois disto, eu fiquei sabendo que eles também estão entregando grandes discontos para quem teve o seu …</p><p>Você teve seu trabalho afetado pela pandemia do covid? Bom, na última semana eu postei no <a href="https://grepora.com/2020/09/17/microsoft-ignite-certification-voucher/">Grepora</a> sobre um Voucher para certificação gratuita que a Microsoft estava distribuindo durante o evento Microsoft Ignite. Depois disto, eu fiquei sabendo que eles também estão entregando grandes discontos para quem teve o seu trabalho afetado pela pandemia do covid. </p> +<p>Para saber se você pode receber este desconto, acesse <a href="https://docs.microsoft.com/en-us/learn/certifications/skillingoffer">https://docs.microsoft.com/en-us/learn/certifications/skillingoffer</a>.</p>O poder do PowerShell2020-09-21T19:00:00-03:002020-09-21T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-09-21:/pt/the-power-of-powershell.html<p>Como um usuário linux por muito tempo, eu automatizei algumas tarefas com scripts bash e fiquei longe do PowerShell... Voltei a utilizar Windows alguns anos atrás e ainda assim, não dei uma chance ao PS. Mas porque não? Eu fiz alguns scripts para automatizar algumas tarefas em um servidor Protheus …</p><p>Como um usuário linux por muito tempo, eu automatizei algumas tarefas com scripts bash e fiquei longe do PowerShell... Voltei a utilizar Windows alguns anos atrás e ainda assim, não dei uma chance ao PS. Mas porque não? Eu fiz alguns scripts para automatizar algumas tarefas em um servidor Protheus.</p> +<p>Eu acabei achando os scripts PS de fácil leitura e entendimento. Abaixo, nós temos um script para remover arquivos filtrando pela sua extensão (ou sem extensão alguma no caso do script em questão).</p> +<div class="highlight"><pre><span></span><code><span class="nb">Get-ChildItem</span> <span class="s2">&quot;C:\TOTVS\protheus_data\system&quot;</span> <span class="o">-File</span> <span class="n">-Filter</span> <span class="p">*.</span> <span class="p">|</span> <span class="nb">Move-Item</span> <span class="n">-Force</span> <span class="n">-Destination</span> <span class="p">{</span> + <span class="cm">&lt;# Diretório ao qual os arquivos vão ser movidos. Você pode utilizar formatos de data para nomear os diretórios #&gt;</span> + <span class="cm">&lt;# LastWriteTime é a propriedade do arquivo corrent #&gt;</span> + <span class="nv">$dir</span> <span class="p">=</span> <span class="s2">&quot;C:\bad_files\{0:yyyy\\MM\\dd}&quot;</span> <span class="o">-f</span> <span class="nv">$_</span><span class="p">.</span><span class="n">LastWriteTime</span> + <span class="nv">$null</span> <span class="p">=</span> <span class="n">mkdir</span> <span class="nv">$dir</span> <span class="n">-Force</span> + <span class="s2">&quot;$dir\</span><span class="p">$(</span><span class="nv">$_</span><span class="p">.</span><span class="n">Name</span><span class="p">)</span><span class="s2">&quot;</span> +<span class="p">}</span> +</code></pre></div> + +<p>Você já precisou remover arquivos baseado no conteúdo de outro arquivo? Abaixo um script onde eu leio um arquivo que contem os nomes de arquivos que eu desejo remover. </p> +<div class="highlight"><pre><span></span><code><span class="k">foreach</span><span class="p">(</span><span class="nv">$line</span> <span class="k">in</span> <span class="nb">Get-Content</span> <span class="p">.\</span><span class="n">Desktop</span><span class="p">\</span><span class="n">bad_files</span><span class="p">.</span><span class="n">txt</span><span class="p">)</span> <span class="p">{</span> + <span class="k">if</span> <span class="p">(</span><span class="nb">Test-Path</span><span class="p">(</span><span class="s1">&#39;\\x.y.z.a\c$\TOTVS\protheus_data\xmls\&#39;</span><span class="p">+</span><span class="nv">$line</span><span class="p">+</span><span class="s1">&#39;.xml&#39;</span><span class="p">))</span> <span class="p">{</span> + <span class="nb">Remove-Item</span><span class="p">(</span><span class="s1">&#39;\\x.y.z.a\c$\TOTVS\protheus_data\xmls\&#39;</span><span class="p">+</span><span class="nv">$line</span><span class="p">+</span><span class="s1">&#39;.xml&#39;</span><span class="p">)</span> + <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> + <span class="nb">echo </span><span class="nv">$line</span> <span class="p">+</span> <span class="s1">&#39; - File not found&#39;</span> + <span class="p">}</span> +<span class="p">}</span> +</code></pre></div> + +<p>E um script bonus para parar e iniciar serviços (se você gerencia um servidor Protheus, você sabe o porque eu faço isto).</p> +<div class="highlight"><pre><span></span><code><span class="nv">$servicesNames</span> <span class="p">=</span> <span class="s1">&#39;app_main&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker1&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker2&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker3&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker4&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker5&#39;</span> + +<span class="nb">Write-host</span> <span class="s2">&quot;Parando Serviços&quot;</span> +<span class="nb">Write-host</span> <span class="s2">&quot;--------------------------&quot;</span> + +<span class="k">foreach</span> <span class="p">(</span><span class="nv">$srv</span> <span class="k">in</span> <span class="nv">$servicesNames</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Write-host</span> <span class="s2">&quot;Parando: &quot;</span> <span class="p">+</span> <span class="nv">$srv</span> + <span class="nv">$SrvPID</span> <span class="p">=</span> <span class="p">(</span><span class="nb">get-wmiobject</span> <span class="n">win32_service</span> <span class="p">|</span> <span class="nb">where </span><span class="p">{</span> <span class="nv">$_</span><span class="p">.</span><span class="n">name</span> <span class="o">-eq</span> <span class="nv">$srv</span><span class="p">}).</span><span class="n">processID</span> + <span class="nb">Write-host</span> <span class="s2">&quot;PID: &quot;</span> <span class="p">+</span> <span class="nv">$SrvPID</span> + + <span class="cm">&lt;# Força a parada caso o serviço esteja travado #&gt;</span> + <span class="nb">Stop-Process</span> <span class="nv">$ServicePID</span> <span class="n">-Force</span> + <span class="nb">Write-host</span> <span class="s2">&quot;PDI &quot;</span> <span class="p">+</span> <span class="nv">$SrvPID</span> <span class="p">+</span> <span class="s2">&quot; parado&quot;</span> +<span class="p">}</span> + + +<span class="nb">Write-host</span> <span class="s2">&quot;Inicializando Serviços&quot;</span> +<span class="nb">Write-host</span> <span class="s2">&quot;--------------------------&quot;</span> + +<span class="k">foreach</span> <span class="p">(</span><span class="nv">$srv</span> <span class="k">in</span> <span class="nv">$servicesNames</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Write-host</span> <span class="s2">&quot;Inicializando: &quot;</span> <span class="p">+</span> <span class="nv">$srv</span> + <span class="nb">Start-Service</span> <span class="nv">$srv</span> +<span class="p">}</span> +</code></pre></div> + +<p>Você tem algum script de automação? Compartilhe conosco :)</p>Top Level Statement no C# 92020-07-29T19:00:00-03:002020-07-29T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-07-29:/pt/top_level_statement_csharp_9.html<p>Olá pessoal, venho hoje falar sobre uma novidade que estará disponível na versão 9 do C#. Toda vez que você deseja criar um novo projeto, você sempre tem o mesmo arquivo Main, com a mesma estrutura. Na próxima versão do C# (versão 9), nós teremos uma nova funcionalidade chamada <code>Top …</code></p><p>Olá pessoal, venho hoje falar sobre uma novidade que estará disponível na versão 9 do C#. Toda vez que você deseja criar um novo projeto, você sempre tem o mesmo arquivo Main, com a mesma estrutura. Na próxima versão do C# (versão 9), nós teremos uma nova funcionalidade chamada <code>Top Level Statement</code>. Com isto, poderemos programar a nossa aplicação sem toda aquela estrutura de <code>namespace/class/public void static main</code>. Veja o código abaixo.</p> +<div class="highlight"><pre><span></span><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span> + +<span class="n">Console</span><span class="p">.</span><span class="n">WriteLine</span><span class="p">(</span><span class="s">&quot;Hello World!&quot;</span><span class="p">);</span> +</code></pre></div> + +<p>Parece muito simples, não é? Com isto, você pode brincar com seu código e até mesmo programar uma pequena WEB API. Para começar a brincar com estas novas <em>features</em>, primeiramente faça o download do preview do <a href="https://dotnet.microsoft.com/download/dotnet/5.0">.net 5 SDK</a> e modifique o seu arquivo <code>.csproj</code> para apontar o framework para <code>.net5.0</code> e a versão de preview da linguagem. Abaixo como uma aplicação de console deve ficar.</p> +<div class="highlight"><pre><span></span><code><span class="nt">&lt;Project</span> <span class="na">Sdk=</span><span class="s">&quot;Microsoft.NET.Sdk&quot;</span><span class="nt">&gt;</span> + <span class="nt">&lt;PropertyGroup&gt;</span> + <span class="nt">&lt;OutputType&gt;</span>Exe<span class="nt">&lt;/OutputType&gt;</span> + <span class="nt">&lt;TargetFramework&gt;</span>net5.0<span class="nt">&lt;/TargetFramework&gt;</span> + <span class="nt">&lt;LangVersion&gt;</span>preview<span class="nt">&lt;/LangVersion&gt;</span> + <span class="nt">&lt;/PropertyGroup&gt;</span> +<span class="nt">&lt;/Project&gt;</span> +</code></pre></div> + +<p>E assim você está pronto para brincar com as novas funcionalidades que estão disponíveis na versão preview. Vamos programar uma aplicação simples que faz uma requisição na API da NASA e printe a Imagem do Dia no console. Não é nenhum código mirabolante, é simplesmente para exemplificar o quão simples uma simples chamada de API pode ser. Feito isto, porque não salvar a imagem como um arquivo? Ou então enviar essa imagem via telegram?</p> +<div class="highlight"><pre><span></span><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Net.Http</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Text.Json</span><span class="p">;</span> + +<span class="kt">var</span> <span class="n">API</span> <span class="p">=</span> <span class="s">&quot;https://api.nasa.gov/planetary/apod?hd=true&amp;api_key=DEMO_KEY&quot;</span><span class="p">;</span> +<span class="kt">var</span> <span class="n">cli</span> <span class="p">=</span> <span class="k">new</span> <span class="n">HttpClient</span><span class="p">();</span> + +<span class="kt">var</span> <span class="n">response</span> <span class="p">=</span> <span class="k">await</span> <span class="n">cli</span><span class="p">.</span><span class="n">GetAsync</span><span class="p">(</span><span class="n">API</span><span class="p">);</span> +<span class="kt">var</span> <span class="n">data</span> <span class="p">=</span> <span class="n">JsonSerializer</span><span class="p">.</span><span class="n">Deserialize</span><span class="p">&lt;</span><span class="n">NasaApi</span><span class="p">&gt;(</span><span class="k">await</span> <span class="n">response</span><span class="p">.</span><span class="n">Content</span><span class="p">.</span><span class="n">ReadAsStringAsync</span><span class="p">());</span> + +<span class="n">Console</span><span class="p">.</span><span class="n">WriteLine</span><span class="p">(</span><span class="n">data</span><span class="p">.</span><span class="n">Url</span><span class="p">);</span> +</code></pre></div> + +<p>Por hoje é isso. Fique de olho nas novas features que o C# 9 vai nos trazer. Já temos várias disponíveis hoje para testar, esta é apenas uma delas.</p>Zabbix poller processes more than 75%2020-07-02T19:00:00-03:002020-07-02T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-07-02:/pt/zabbix-poller-processes-more-than-75.html<p>Este é o terceiro post sobre configurações para o Zabbix. Todas as alterações que eu sugiro nestes posts, são baseadas em um servidor com 50+ hosts. Outro problema que pode ocorrer em seu servidor, é o poller de informações ficar sobrecarregado pela quantidade de servidores que ele precisa pegar carga …</p><p>Este é o terceiro post sobre configurações para o Zabbix. Todas as alterações que eu sugiro nestes posts, são baseadas em um servidor com 50+ hosts. Outro problema que pode ocorrer em seu servidor, é o poller de informações ficar sobrecarregado pela quantidade de servidores que ele precisa pegar carga de informações juntamente com os servidores que não respondem a requisição. Abaixo duas imagens onde você pode ver o log e um gráfico onde aparecem os percentuais de uso dos poller. </p> +<p><img alt="Dashboard log sobre o processo do poller" src="/images/zabbix_pooler.png"></p> +<p><img alt="Gráfico mostrando o percentual de utilização de cada coletor" src="/images/zabbix_pooler_3.png"></p> +<p>Para resolver o problema acima, vamos voltar ao arquivo de configuração <code>zabbix_server.conf</code> e localizar duas variáveis, <code>StartPollers</code> e <code>StartPollersUnreachable</code>. Aumente o valor delas conforme necessário. Não existe um número mágico, você deve verificar o que melhor funciona para você. Mas tenha em mente que <code>StartPollersUnreachable</code> é responsável por aqueles hosts que não respondem ou não são localizados e irão segurar a thread do poller por mais tempo, causando uma fila e um maior processamento/tempo de atualização.</p> +<div class="highlight"><pre><span></span><code><span class="c1">### Option: StartPollers</span> +<span class="c1"># Number of pre-forked instances of pollers.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 0-1000</span> +<span class="c1"># Default:</span> +<span class="na">StartPollers</span><span class="o">=</span><span class="s">20</span> + +<span class="c1">#...</span> + +<span class="c1">### Option: StartPollersUnreachable</span> +<span class="c1"># Number of pre-forked instances of pollers for unreachable hosts (including IPMI and Java).</span> +<span class="c1"># At least one poller for unreachable hosts must be running if regular, IPMI or Java pollers</span> +<span class="c1"># are started.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 0-1000</span> +<span class="c1"># Default:</span> +<span class="na">StartPollersUnreachable</span><span class="o">=</span><span class="s">5</span> +</code></pre></div> + +<p>Depois da alteração, reinicie o serviço e espere alguns momentos e veja o seu dashboard novamente. Abaixo o efeito que a troca teve em um dos servidores que acompanho.</p> +<p><img alt="Gráfico mostrando os novos percentuais de utilização dos processos após as alterações" src="/images/zabbix_pooler_4.png"></p>Monitorando a disponibilidade de um Website com Azure Functions2020-06-22T19:00:00-03:002020-06-22T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-06-22:/pt/monitoring-website-heath-with-azure-functions.html<p>Algumas vezes você se depara com a necessidade de monitorar a disponibilidade de um website ou mudanças em seu conteúdo. É claro que temos diversas opções disponíveis no mercado, mas para fins de curiosidade, vamos programar o nosso próprio e ver o que podemos fazer. Primeiramente, tudo que você ver …</p><p>Algumas vezes você se depara com a necessidade de monitorar a disponibilidade de um website ou mudanças em seu conteúdo. É claro que temos diversas opções disponíveis no mercado, mas para fins de curiosidade, vamos programar o nosso próprio e ver o que podemos fazer. Primeiramente, tudo que você ver aqui, você pode utilizar o <a href="https://azure.microsoft.com/free/">tier gratuito</a> da Azure.</p> +<p>A ideia principal da nossa aplicação vai ser monitorar a disponibilidade do website (status code). Para criar um projeto de Azure Function, siga os passos abaixo.</p> +<p><img alt="Passos para criar um projeto Azure Functions" src="/images/azure_functions.gif"></p> +<p>Depois de criar o projeto, você vai ter alguns arquivos. Abra o arquivo principal (<code>HttpCheck.cs</code> no meu caso) e começe a programar. O arquivo principal terá uma função chamada <code>Run</code> e você pode progamar nela o seu request. Eu criei um método <code>async</code> para fazer as requisições e printar a saída diretamente no console. O código completo pode ser visto abaixo.</p> +<div class="highlight"><pre><span></span><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Linq</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Net.Http</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Threading.Tasks</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">Microsoft.Azure.WebJobs</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">Microsoft.Azure.WebJobs.Host</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">Microsoft.Extensions.Logging</span><span class="p">;</span> + +<span class="k">namespace</span> <span class="nn">Sipmann.CheckMySite</span> +<span class="p">{</span> + <span class="k">public</span> <span class="k">static</span> <span class="k">class</span> <span class="nc">HttpCheck</span> + <span class="p">{</span> + + <span class="k">private</span> <span class="k">static</span> <span class="k">async</span> <span class="n">Task</span> <span class="nf">GetTask</span><span class="p">(</span><span class="kt">string</span> <span class="n">url</span><span class="p">,</span> <span class="n">ILogger</span> <span class="n">log</span><span class="p">)</span> + <span class="p">{</span> + <span class="kt">var</span> <span class="n">request</span> <span class="p">=</span> <span class="k">new</span> <span class="n">HttpRequestMessage</span><span class="p">(</span><span class="n">HttpMethod</span><span class="p">.</span><span class="n">Get</span><span class="p">,</span> <span class="n">url</span><span class="p">);</span> + + <span class="kt">var</span> <span class="n">client</span> <span class="p">=</span> <span class="k">new</span> <span class="n">HttpClient</span><span class="p">();</span> + <span class="kt">var</span> <span class="n">response</span> <span class="p">=</span> <span class="k">await</span> <span class="n">client</span><span class="p">.</span><span class="n">SendAsync</span><span class="p">(</span><span class="n">request</span><span class="p">);</span> + + <span class="k">if</span> <span class="p">(</span><span class="n">response</span><span class="p">.</span><span class="n">IsSuccessStatusCode</span><span class="p">)</span> + <span class="p">{</span> + <span class="n">log</span><span class="p">.</span><span class="n">LogInformation</span><span class="p">(</span><span class="err">$</span><span class="s">&quot;URL ${url} esta OK&quot;</span><span class="p">);</span> + <span class="p">}</span> + <span class="k">else</span> + <span class="p">{</span> + <span class="n">log</span><span class="p">.</span><span class="n">LogInformation</span><span class="p">(</span><span class="err">$</span><span class="s">&quot;URL ${url} não esta OK&quot;</span><span class="p">);</span> + <span class="p">}</span> + <span class="p">}</span> + +<span class="na"> [FunctionName(&quot;HttpCheck&quot;)]</span> + <span class="k">public</span> <span class="k">static</span> <span class="k">void</span> <span class="nf">Run</span><span class="p">([</span><span class="n">TimerTrigger</span><span class="p">(</span><span class="s">&quot;0 */5 * * * *&quot;</span><span class="p">)]</span><span class="n">TimerInfo</span> <span class="n">myTimer</span><span class="p">,</span> <span class="n">ILogger</span> <span class="n">log</span><span class="p">)</span> + <span class="p">{</span> + <span class="c1">// URL a verificar a saúde</span> + <span class="kt">var</span> <span class="n">urls</span> <span class="p">=</span> <span class="k">new</span><span class="p">[]{</span><span class="s">&quot;https://www.sipmann.com&quot;</span><span class="p">,</span> <span class="s">&quot;https://www.canezecanez.com.br&quot;</span><span class="p">};</span> + + <span class="c1">// Starta cada request e aguarda todos de uma vez só</span> + <span class="n">Task</span><span class="p">.</span><span class="n">WaitAll</span><span class="p">(</span><span class="n">urls</span><span class="p">.</span><span class="n">Select</span><span class="p">(</span><span class="n">url</span> <span class="p">=&gt;</span> <span class="n">GetTask</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">log</span><span class="p">)).</span><span class="n">ToArray</span><span class="p">());</span> + <span class="n">log</span><span class="p">.</span><span class="n">LogInformation</span><span class="p">(</span><span class="err">$</span><span class="s">&quot;Finalizou a fila&quot;</span><span class="p">);</span> + <span class="p">}</span> + <span class="p">}</span> +<span class="p">}</span> +</code></pre></div> + +<p>Agora você pode melhorar a função e talvez enviar alguns alertas. Como por exêmplo mensagens no Telegram quando um dos sites ficar off (status code 404).</p>Zabbix ICMP pinger processes more than 75%2020-05-25T16:00:00-03:002020-05-25T16:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-05-25:/pt/zabbix-icmp-pinger-processes-more-than-75.html<p>Então o seu systema de monitoramento creasceu e o seu Zabbix começou a printar "<em>Zabbix icmp pinger processes more than 75% busy</em>" no seu dashboard.</p> +<p><img alt="Dashboard do zabbix avisando sobre o erro" src="/images/zabbix_pinger01.png"></p> +<p>Tudo que você tem a fazer é abrir o seu arquivo de configuração (<code>/etc/zabbix/zabbix_server.conf</code>) e localizar a tag chamada <code>StartPingers</code>. Ela deve …</p><p>Então o seu systema de monitoramento creasceu e o seu Zabbix começou a printar "<em>Zabbix icmp pinger processes more than 75% busy</em>" no seu dashboard.</p> +<p><img alt="Dashboard do zabbix avisando sobre o erro" src="/images/zabbix_pinger01.png"></p> +<p>Tudo que você tem a fazer é abrir o seu arquivo de configuração (<code>/etc/zabbix/zabbix_server.conf</code>) e localizar a tag chamada <code>StartPingers</code>. Ela deve estar comentáda por padrão. Descomente a lina e define o seu valor para algo como 3 or 4. Deve resolver seu problema, ao menos até um próximo crescimento do seu monitoramento.</p> +<div class="highlight"><pre><span></span><code><span class="c1">### Option: StartPingers</span> +<span class="c1"># Number of pre-forked instances of ICMP pingers.</span> +<span class="c1">#</span> +<span class="c1"># Mandatory: no</span> +<span class="c1"># Range: 0-1000</span> +<span class="c1"># Default:</span> +<span class="nv">StartPingers</span><span class="o">=</span><span class="m">4</span> +</code></pre></div>Zabbix Server Out of Memory2020-02-27T19:00:00-03:002020-02-27T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-02-27:/pt/zabbix-server-out-of-memory-crash.html<p>Você tem um servidor Zabbix crashando e observando o arquivo de log <code>/var/log/zabbix/zabbix_server.log</code> você localiza a seguinte mensagem referênciando falta de memória?</p> +<div class="highlight"><pre><span></span><code>__mem_malloc: skipped <span class="m">0</span> asked <span class="m">24</span> skip_min <span class="m">18446744073709551615</span> skip_max <span class="m">0</span> +<span class="o">[</span>file:dbconfig.c,line:94<span class="o">]</span> __zbx_mem_realloc<span class="o">()</span>: out of memory <span class="o">(</span>requested <span class="m">16</span> bytes<span class="o">)</span> +<span class="o">[</span>file:dbconfig.c …</code></pre></div><p>Você tem um servidor Zabbix crashando e observando o arquivo de log <code>/var/log/zabbix/zabbix_server.log</code> você localiza a seguinte mensagem referênciando falta de memória?</p> +<div class="highlight"><pre><span></span><code>__mem_malloc: skipped <span class="m">0</span> asked <span class="m">24</span> skip_min <span class="m">18446744073709551615</span> skip_max <span class="m">0</span> +<span class="o">[</span>file:dbconfig.c,line:94<span class="o">]</span> __zbx_mem_realloc<span class="o">()</span>: out of memory <span class="o">(</span>requested <span class="m">16</span> bytes<span class="o">)</span> +<span class="o">[</span>file:dbconfig.c,line:94<span class="o">]</span> __zbx_mem_realloc<span class="o">()</span>: please increase CacheSize configuration parameter +</code></pre></div> + +<p>Apesar da simples solução para o erro, isso acaba sendo um problema comum em servidores que tem uma certa quantidade de itens sendo monitorados (servidores, switches, firewalls, bancos, etc...). Para resolver o problema, vá até o ser arquivo <code>zabbix_server.conf</code> e procure pela propriedade <code>CacheSize</code> e sete o seu valor para uma quantidade maior. O seu valor default deve ser algo como 8M. Em clientes que tenham algo como 4 servidores, 7 firewalls/appliances, e algumas outras coisas (bancos, apps), 32M deve resolver o problema, mas você pode setar até algo como 8G (ressalto que mais memória nem sempre é melhor).</p> +<p>Até breve.</p>Removendo um usuário de uma base SQL Server2019-09-06T07:00:00-03:002020-10-21T18:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2019-09-06:/pt/removing-user-from-sql-server-database.html<p>O seu cliente lhe pede com urgência para <em>dropar</em> um usuário da sua base MsSQL Server, mas você trava com o seguinte aviso de erro:</p> +<div class="highlight"><pre><span></span><code><span class="n">Error</span><span class="o">:</span> <span class="mi">15138</span> <span class="n">The</span> <span class="n">database</span> <span class="n">principal</span> <span class="n">owns</span> <span class="n">a</span> <span class="n">schema</span> <span class="k">in</span> <span class="n">the</span> <span class="n">database</span><span class="o">,</span> <span class="n">and</span> <span class="n">cannot</span> <span class="n">be</span> <span class="n">dropped</span><span class="o">.</span> +</code></pre></div> + +<p>Se você não possui (ou no momento não consegue acesso …</p><p>O seu cliente lhe pede com urgência para <em>dropar</em> um usuário da sua base MsSQL Server, mas você trava com o seguinte aviso de erro:</p> +<div class="highlight"><pre><span></span><code><span class="n">Error</span><span class="o">:</span> <span class="mi">15138</span> <span class="n">The</span> <span class="n">database</span> <span class="n">principal</span> <span class="n">owns</span> <span class="n">a</span> <span class="n">schema</span> <span class="k">in</span> <span class="n">the</span> <span class="n">database</span><span class="o">,</span> <span class="n">and</span> <span class="n">cannot</span> <span class="n">be</span> <span class="n">dropped</span><span class="o">.</span> +</code></pre></div> + +<p>Se você não possui (ou no momento não consegue acesso) ao SSMS (SQL Server Management Studio) para verificar quais schemas ou objetos o usuário é "dono", a seguinte SQL vai resolver o problema.</p> +<div class="highlight"><pre><span></span><code><span class="k">USE</span><span class="w"> </span><span class="o">[</span><span class="n">DATABASENAME</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> + +<span class="k">select</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Objeto</span><span class="p">,</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Owner</span><span class="w"></span> +<span class="k">from</span><span class="w"> </span><span class="n">sys</span><span class="p">.</span><span class="n">schemas</span><span class="w"> </span><span class="n">so</span><span class="w"></span> +<span class="k">inner</span><span class="w"> </span><span class="k">join</span><span class="w"> </span><span class="n">sysusers</span><span class="w"> </span><span class="n">su</span><span class="w"> </span><span class="k">on</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">principal_id</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">uid</span><span class="w"></span> +<span class="k">where</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">&#39;username&#39;</span><span class="w"></span> + +<span class="k">select</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Objeto</span><span class="p">,</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Owner</span><span class="p">,</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">xtype</span><span class="w"> </span><span class="n">Tipo</span><span class="w"></span> +<span class="k">from</span><span class="w"> </span><span class="n">sys</span><span class="p">.</span><span class="n">sysobjects</span><span class="w"> </span><span class="n">so</span><span class="w"></span> +<span class="k">inner</span><span class="w"> </span><span class="k">join</span><span class="w"> </span><span class="n">sysusers</span><span class="w"> </span><span class="n">su</span><span class="w"> </span><span class="k">on</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">uid</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">uid</span><span class="w"></span> +<span class="k">where</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">&#39;username&#39;</span><span class="w"></span> +</code></pre></div> + +<p>Assim que você tiver os objetos/schemas que o usuário é dono, você pode alterar os mesmos com a seguinte SQL (exemplo de troca de schema):</p> +<div class="highlight"><pre><span></span><code><span class="k">USE</span><span class="w"> </span><span class="o">[</span><span class="n">DATABASENAME</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +<span class="k">ALTER</span><span class="w"> </span><span class="k">AUTHORIZATION</span><span class="w"> </span><span class="k">ON</span><span class="w"> </span><span class="k">SCHEMA</span><span class="o">::[</span><span class="n">db_datareader</span><span class="o">]</span><span class="w"> </span><span class="k">TO</span><span class="w"> </span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="w"> </span><span class="c1">-- username do novo dono</span> +<span class="k">ALTER</span><span class="w"> </span><span class="k">AUTHORIZATION</span><span class="w"> </span><span class="k">ON</span><span class="w"> </span><span class="k">SCHEMA</span><span class="o">::[</span><span class="n">db_datawriter</span><span class="o">]</span><span class="w"> </span><span class="k">TO</span><span class="w"> </span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +</code></pre></div> + +<p>Então, você pode dropar o usuário <code>DROP USER [username]</code>.</p>Resolvendo java.net.SocketException: Protocol family unavailable em Java + Docker + WildFly2018-03-04T17:40:00-03:002018-03-04T17:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-03-04:/pt/socketException-protocol-family-unavailable-java-docker-wildfly.html<p>Nos últimos dias eu estou brincando com o <a class="reference external" href="http://wildfly-swarm.io/">WildFly Swarm</a> e decidi fazer o deploy de uma aplicação simples com Docker. Deveria funcionar bem, ao menos é o que pensava. Construí um container com o seguinte Dockerfile e ao invés de obter uma aplicação web, tudo que eu obtive foi …</p><p>Nos últimos dias eu estou brincando com o <a class="reference external" href="http://wildfly-swarm.io/">WildFly Swarm</a> e decidi fazer o deploy de uma aplicação simples com Docker. Deveria funcionar bem, ao menos é o que pensava. Construí um container com o seguinte Dockerfile e ao invés de obter uma aplicação web, tudo que eu obtive foi o erro <cite>java.net.SocketException: Protocol family unavailable</cite>.</p> +<div class="highlight"><pre><span></span><span class="k">FROM</span> <span class="s">java:openjdk-8-jdk</span> + +<span class="k">COPY</span> target/issues.jar /opt/issues.jar + +<span class="k">EXPOSE</span><span class="s"> 8080</span> + +<span class="k">CMD</span> <span class="p">[</span><span class="s2">&quot;java&quot;</span><span class="p">,</span><span class="s2">&quot;-jar&quot;</span><span class="p">,</span><span class="s2">&quot;/opt/issues.jar&quot;</span><span class="p">]</span> +</pre></div> +<p>Por alguma razão, WildFly e Java, ambos decidiram utilizar um protocolo IPv6 na interface de rede no Docker invés da v4, então tudo que você tem que fazer é falar ao Java que deve dar preferência em utilizar o IPv4 com a seguinte configuração no seu arquivo pom.xml dentro da tag do plugin WildFly.</p> +<div class="highlight"><pre><span></span><span class="nt">&lt;plugin&gt;</span> + <span class="nt">&lt;groupId&gt;</span>org.wildfly.swarm<span class="nt">&lt;/groupId&gt;</span> + <span class="nt">&lt;artifactId&gt;</span>wildfly-swarm-plugin<span class="nt">&lt;/artifactId&gt;</span> + <span class="nt">&lt;version&gt;</span>2018.2.0<span class="nt">&lt;/version&gt;</span> + + <span class="c">&lt;!-- ADICIONE ISTO --&gt;</span> + <span class="nt">&lt;configuration&gt;</span> + <span class="nt">&lt;mainClass&gt;</span>org.wildfly.swarm.examples.netflix.ribbon.frontend.Main<span class="nt">&lt;/mainClass&gt;</span> + <span class="nt">&lt;properties&gt;</span> + <span class="nt">&lt;java.net.preferIPv4Stack&gt;</span>true<span class="nt">&lt;/java.net.preferIPv4Stack&gt;</span> + <span class="nt">&lt;/properties&gt;</span> + <span class="nt">&lt;/configuration&gt;</span> +</pre></div> +<p>Outra forma de solucionar o problema, é adicionando a mesma propriedade ao comando de run no seu Dockerfile. Então, fica a seu critério onde adicionar. Abaixo a solução utilizando o Dockerfile.</p> +<div class="highlight"><pre><span></span><span class="k">FROM</span> <span class="s">java:openjdk-8-jdk</span> +<span class="k">ENV</span> <span class="nv">JAVA_OPTS</span><span class="o">=</span><span class="s2">&quot;-Djava.net.preferIPv4Stack=true -Djava.net.preferIPv4Addresses=true&quot;</span> + +<span class="k">COPY</span> target/issues.jar /opt/issues.jar + +<span class="k">EXPOSE</span><span class="s"> 8080</span> + +<span class="k">ENTRYPOINT</span> <span class="nb">exec</span> java <span class="nv">$JAVA_OPTS</span> -jar /opt/issues.jar +</pre></div> +Menu dinâmico com as apps do django2018-01-21T21:17:00-02:002018-01-21T21:17:00-02:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-01-21:/pt/menu-dinamico-com-apps-do-django.html<p>Digamos que sua empresa trabalha com Django desenvolvendo aplicações cujas apps são plugaveis e reutilizáveis. Por que não se aproveitar de um certo padrão de desenvolvimento para desenvolver menus que se modificam de acordo com as apps que estão no projeto? Como o objetivo aqui não é desenvolver uma app …</p><p>Digamos que sua empresa trabalha com Django desenvolvendo aplicações cujas apps são plugaveis e reutilizáveis. Por que não se aproveitar de um certo padrão de desenvolvimento para desenvolver menus que se modificam de acordo com as apps que estão no projeto? Como o objetivo aqui não é desenvolver uma app em si, vamos utilizar um projeto com algumas de modelo. Se desejar estudar mais sobre desenvolvimento Django, a documentação é muito boa, mas também temos blogs e sites excelentes sobre o assunto.</p> +<p>Para conseguirmos atingir esse objetivo, vamos utilizar a api <a class="reference external" href="https://docs.djangoproject.com/en/2.0/ref/settings/#installed-apps">Django.apps</a> que está disponível a partir da versão 1.7. +Com esta api, vamos percorrer as apps e se possível, criar um link para uma URL base de cada uma delas. Para começo, baixe os fontes do <a class="reference external" href="https://github.com/sipmann/menusapp-django/releases/tag/v1">projeto aqui</a>, rode o pip install do projeto e no fim, sua estrutura de pastas deve ficar como abaixo.</p> +<div class="highlight"><pre><span></span>../menusapp/ +├── comentarios +│ ├── templates +│ │ └── comentarios +│ │ └── listagem.html +│ ├── __init__.py +│ ├── admin.py +│ ├── apps.py +│ ├── models.py +│ ├── tests.py +│ ├── urls.py +│ └── views.py +├── core +│ ├── templates +│ │ └── core +│ │ └── base.html +│ │ └── listagem.html +│ ├── __init__.py +│ ├── admin.py +│ ├── apps.py +│ ├── models.py +│ ├── tests.py +│ ├── urls.py +│ └── views.py +├── menusapp +│ ├── __init__.py +│ ├── settings.py +│ ├── urls.py +│ └── wsgi.py +└── manage.py +</pre></div> +<p>Rode o projeto e veja como é o seu funcionamento. É na app core que temos a base do nosso HTML, então será nele que iremos trabalhar. Quando se trata de algo que será renderizado no template base, eu gosto muito de utilizar 'template tags' para facilitar. +Neste <a class="reference external" href="http://www.sipmann.com/editando-o-admin-do-django.html">link</a> tem mais um exemplo de utilização de 'template tag' caso esteja interessado.</p> +<p>Vamos então criar uma pasta chamada template_tag e dentro dela a nossa tag. Vamos chamá-la de menus_tag.py. Abaixo vamos ver um pouco da nossa tag. +O código é bem simples e auto explicativo, importamos as bibliotecas necessárias e realizamos o &#64;register da tag com o nome do template que será renderizado. +E por ultimo, retornamos uma tupla de dados para o template.</p> +<div class="livros"> + <div class="recomendacoes">Recomendações</div> + <a rel="noopener" href="https://www.amazon.com.br/gp/product/8575225081/ref=as_li_ss_il?ie=UTF8&linkCode=li2&tag=sipmann-20&linkId=c17fa3ac84e734741a3761e874d7d286" target="_blank"><img border="0" src="//ws-na.amazon-adsystem.com/widgets/q?_encoding=UTF8&ASIN=8575225081&Format=_SL160_&ID=AsinImage&MarketPlace=BR&ServiceVersion=20070822&WS=1&tag=sipmann-20" ></a><img src="https://ir-br.amazon-adsystem.com/e/ir?t=sipmann-20&l=li2&o=33&a=8575225081" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /> + <a rel="noopener" href="https://www.amazon.com.br/gp/product/B074ZTLKHB/ref=as_li_ss_il?ie=UTF8&linkCode=li2&tag=sipmann-20&linkId=e2f37c07da2dc4111ae47854b205d01a" target="_blank"><img border="0" src="//ws-na.amazon-adsystem.com/widgets/q?_encoding=UTF8&ASIN=B074ZTLKHB&Format=_SL160_&ID=AsinImage&MarketPlace=BR&ServiceVersion=20070822&WS=1&tag=sipmann-20" ></a><img src="https://ir-br.amazon-adsystem.com/e/ir?t=sipmann-20&l=li2&o=33&a=B074ZTLKHB" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /> +</div><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django</span> <span class="kn">import</span> <span class="n">template</span> +<span class="kn">from</span> <span class="nn">django.apps</span> <span class="kn">import</span> <span class="n">apps</span> + +<span class="c1">#Carrega o registro de template tags</span> +<span class="n">register</span> <span class="o">=</span> <span class="n">template</span><span class="o">.</span><span class="n">Library</span><span class="p">()</span> + +<span class="c1">#Registra o metodo a seguir como uma inclusion_tag indicando o template a ser renderizado</span> +<span class="nd">@register</span><span class="o">.</span><span class="n">inclusion_tag</span><span class="p">(</span><span class="s1">&#39;menus_por_app.html&#39;</span><span class="p">)</span> +<span class="k">def</span> <span class="nf">menus_por_app</span><span class="p">():</span> + <span class="n">lst</span> <span class="o">=</span> <span class="n">apps</span><span class="o">.</span><span class="n">get_app_configs</span><span class="p">()</span> + <span class="k">return</span> <span class="p">{</span> <span class="s1">&#39;lst_apps&#39;</span> <span class="p">:</span> <span class="n">lst</span> <span class="p">}</span> +</pre></div> +<p>O template está abaixo e é simplesmente um for percorrendo as apps e gerando uma lista com os seus menus. As outras propriedades você pode ver direto na <a class="reference external" href="https://docs.djangoproject.com/en/2.0/ref/applications/#django.apps.AppConfig">documentação</a>. +Algumas ressalvas para o que foi feito por questões de praticidade para uso posterior, utilizei um with para concatenar e gerar a url e criei um apelido para a url para validar a existência da mesma. Fora isto, nada de novo.</p> +<div class="highlight"><pre><span></span>{% if not lst_apps %} + <span class="p">&lt;</span><span class="nt">p</span><span class="p">&gt;</span>Nenhuma app<span class="p">&lt;/</span><span class="nt">p</span><span class="p">&gt;</span> + {% else %} + <span class="p">&lt;</span><span class="nt">ul</span><span class="p">&gt;</span> + {% for app in lst_apps %} + {% with app.name|add:&quot;:listagem&quot; as link %} + {% url link as the_url %} + {% if the_url %} + <span class="p">&lt;</span><span class="nt">li</span><span class="p">&gt;</span> + <span class="p">&lt;</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">&quot;{% url link %}&quot;</span><span class="p">&gt;</span>{{ app.verbose_name|truncatechars:30 }}<span class="p">&lt;/</span><span class="nt">a</span><span class="p">&gt;</span> + <span class="p">&lt;/</span><span class="nt">li</span><span class="p">&gt;</span> + {% endif %} + {% endwith %} + {% endfor %} + <span class="p">&lt;/</span><span class="nt">ul</span><span class="p">&gt;</span> + {% endif %} +</pre></div> +<img alt="Resultado final" src="/images/menu_apps.png" /> +<p>No final, o resultado obtido deve ser semelhante ao acima. Repare que está listando as duas aplicações. E acima de tudo, repare que só serão exibidos os links cuja app tenha um namespace de mesmo nome e uma url de nome <cite>listagem</cite>. +A estrutura final pode ser vista abaixo. Atente-se aos nomes tanto das pastas quanto dos arquivos, pois qualquer diferença pode causar o não funcionamento.</p> +<div class="highlight"><pre><span></span>../menusapp/ +├── comentarios +│ ├── templates +│ │ └── comentarios +│ │ └── listagem.html +│ ├── __init__.py +│ ├── admin.py +│ ├── apps.py +│ ├── models.py +│ ├── tests.py +│ ├── urls.py +│ └── views.py +├── core +│ ├── templates +│ │ └── core +│ │ │ └── base.html +│ │ │ └── listagem.html +│ │ └── menus_por_app.html +│ ├── templatetags +│ │ ├── __init__.py +│ │ └── menus_tag.py +│ ├── __init__.py +│ ├── admin.py +│ ├── apps.py +│ ├── models.py +│ ├── tests.py +│ ├── urls.py +│ └── views.py +├── menusapp +│ ├── __init__.py +│ ├── settings.py +│ ├── urls.py +│ └── wsgi.py +└── manage.py +</pre></div> +<p>Espero que tenham gostado, críticas e sugestões são bem-vindas. <a class="reference external" href="https://github.com/sipmann/menusapp-django/releases/tag/v2">Fontes do Projeto</a></p> +Scripts de inicialização no raspberry pi2017-10-08T18:00:00-03:002017-10-08T18:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2017-10-08:/pt/script-de-inicializacao-raspberry.html<p>Instalei essa semana o <a class="reference external" href="https://gitea.io">gitea</a> no meu raspberry pi B + e queria iniciar ele no boot... Não sou profundo conhecedor de linux, então, logo não sabia como fazer isto da melhor forma. +As versões atuais do Raspbian utilizam o <cite>systemd</cite> para gerenciar os serviços e confesso que nunca havia utilizado …</p><p>Instalei essa semana o <a class="reference external" href="https://gitea.io">gitea</a> no meu raspberry pi B + e queria iniciar ele no boot... Não sou profundo conhecedor de linux, então, logo não sabia como fazer isto da melhor forma. +As versões atuais do Raspbian utilizam o <cite>systemd</cite> para gerenciar os serviços e confesso que nunca havia utilizado o systemctl para nada.</p> +<p>Vamos começa criando um arquivo de serviço dentro da pasta <cite>/etc/systemd/system</cite>, vale ressaltar que a pasta <cite>system</cite> deve (em teoria) ser reservada para pacotes do sistema. +Vamos criar o arquivo com o nome <cite>gitea.service</cite> dentro da pasta antes mencionada. Abaixo podemos ver como ficou o arquivo e um detalhamento após ele.</p> +<div class="highlight"><pre><span></span><span class="o">[</span>Unit<span class="o">]</span> +<span class="nv">Description</span><span class="o">=</span>Gitea Service +<span class="nv">After</span><span class="o">=</span>network.target + +<span class="o">[</span>Service<span class="o">]</span> +<span class="nv">Type</span><span class="o">=</span>simple +<span class="nv">User</span><span class="o">=</span>root +<span class="nv">WorkingDirectory</span><span class="o">=</span>/root/ +<span class="nv">ExecStart</span><span class="o">=</span>/root/gitea web +<span class="nv">Restart</span><span class="o">=</span>on-abort +</pre></div> +<p>A composição do arquivo é bem simples, mas vamos a alguns detalhes. <cite>Type</cite> possui várias opções (simple, forking, oneshot), utilizamos <cite>simple</cite> uma vez que o nosso processo executara, permanecerá rodando e não executa um fork de processo. +Fork como acabo de comentar, deve ser utilizado caso o processo que for executando disparar mais processos. User irá definir o usuário do processo. <cite>WorkingDirectory</cite> definira onde o processo terá a sua base de execução, como o gitea esta localizada na pasta root, +aponto para lá. O ExecStart é bem simples e direto, deve chamar a execução do processo passando parametros caso seja necessário. O <cite>Restart</cite> é o que nos garantirá que o serviço permanecerá rodando caso haja algum imprevisto (exceto o fato de um usuário chamar o stop).</p> +<p>Salve o arquivo e vamos rodar um refresh para o SO perceber o novo serviço. Assim rodamos <cite>systemctl daemon-reload</cite>. Sempre que alterarmos um serviço ou criarmos um novo, este comando deve ser executado, caso contrário o próprio systemctl pode lhe alertar da necessidade. +Após reacarregar os serviços, vamos habilitar o serviço que criamos rodando <cite>systemctl enable gitea</cite>, feito isto temos alguns comandos uteis.</p> +<ul class="simple"> +<li>systemctl start gitea</li> +<li>systemctl stop gitea</li> +<li>systemctl status gitea</li> +</ul> +<p>O comando de status pode ser visto como exemplo abaixo.</p> +<div class="highlight"><pre><span></span>● gitea.service - Gitea Service + Loaded: loaded <span class="o">(</span>/etc/systemd/system/gitea.service<span class="p">;</span> enabled<span class="p">;</span> vendor preset: enabled<span class="o">)</span> + Active: active <span class="o">(</span>running<span class="o">)</span> since Wed <span class="m">2017</span>-10-04 <span class="m">00</span>:37:34 UTC<span class="p">;</span> 52min ago +Main PID: <span class="m">1087</span> <span class="o">(</span>gitea<span class="o">)</span> + CGroup: /system.slice/gitea.service + └─1087 /root/gitea web + +Oct <span class="m">04</span> <span class="m">00</span>:38:31 gitserver gitea<span class="o">[</span><span class="m">1087</span><span class="o">]</span>: <span class="o">[</span>Macaron<span class="o">]</span> <span class="m">2017</span>-10-04 <span class="m">00</span>:38:31: Completed /explore/users <span class="m">200</span> OK in <span class="m">80</span>.106173ms +Oct <span class="m">04</span> <span class="m">00</span>:38:31 gitserver gitea<span class="o">[</span><span class="m">1087</span><span class="o">]</span>: <span class="o">[</span>Macaron<span class="o">]</span> <span class="m">2017</span>-10-04 <span class="m">00</span>:38:31: Started GET /img/favicon.png <span class="k">for</span> <span class="m">192</span>.168.1.4 +Oct <span class="m">04</span> <span class="m">00</span>:38:31 gitserver gitea<span class="o">[</span><span class="m">1087</span><span class="o">]</span>: <span class="o">[</span>Macaron<span class="o">]</span> <span class="o">[</span>Static<span class="o">]</span> Serving /img/favicon.png +</pre></div> +<p>Após estes processos, você pode reiniciar seu raspberry que o gitea irá subir e funcionar. Ressalto que, preste atenção tanto no <cite>WorkingDirectory</cite> quanto no <cite>ExecStart</cite>, no caso do gitea, ele utiliza o workingdir e a forma de start para saber onde irá largar os arquivos por padrão, então ou você configura ele com caminhos absolutos ou cuidar na forma de start (ao menos é o que consegui pegar até agora).</p> +Cool Tools2017-09-17T14:00:00-03:002017-09-17T14:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2017-09-17:/pt/cool-tools.html<p>Com o passar do tempo você vai &quot;encontrando&quot; - e às vezes até mesmo desenvolvendo - algumas ferramentas que tornam o seu dia a dia como desenvolvedor mais fácil. Abaixo seguem algumas das minhas ferramentas que costumo usar. Ressalto que essa lista será (provavelmente) atualizada com o passar do tempo.</p> +<div class="section" id="https-www-gitkraken-com"> +<h2><a class="reference external" href="https://www.gitkraken.com">https://www …</a></h2></div><p>Com o passar do tempo você vai &quot;encontrando&quot; - e às vezes até mesmo desenvolvendo - algumas ferramentas que tornam o seu dia a dia como desenvolvedor mais fácil. Abaixo seguem algumas das minhas ferramentas que costumo usar. Ressalto que essa lista será (provavelmente) atualizada com o passar do tempo.</p> +<div class="section" id="https-www-gitkraken-com"> +<h2><a class="reference external" href="https://www.gitkraken.com">https://www.gitkraken.com</a></h2> +<p>Eu gosto muito de usar git, mas às vezes fico cansado de ter que usar só linha de comando, e achei no GitKreaken uma interface muito legal de se usar.</p> +</div> +<div class="section" id="http-paletton-com"> +<h2><a class="reference external" href="http://paletton.com">http://paletton.com</a></h2> +<p>Toda vez que você vai fazer um novo sistema/site, ou até mesmo trocar o layout de algum já existente, você acaba tendo que montar uma paleta de cores para se utilizar em todo o template.</p> +</div> +<div class="section" id="https-icomoon-io-app-select"> +<h2><a class="reference external" href="https://icomoon.io/app/#/select">https://icomoon.io/app/#/select</a></h2> +<p>Querendo usar ícones como fontes? Vá aí e gere apenas os arquivos que você vai realmente utilizar e economize alguns kbs.</p> +</div> +<div class="section" id="https-syncthing-net"> +<h2><a class="reference external" href="https://syncthing.net/">https://syncthing.net/</a></h2> +<p>Se você procura algum meio de sincronizar seus arquivos entre vários pcs e por algum motivo não quer usar um Google Drive ou DropBox, fica aqui a indicação deste cara.</p> +</div> +<div class="section" id="http-sqitch-org"> +<h2><a class="reference external" href="http://sqitch.org/">http://sqitch.org/</a></h2> +<p>Gerenciamento de versões de um banco de dados pode ser bem complicado e trabalhoso... Manter diversos ambientes (desenvolvimento, homologação, produção) vai dar um trabalho se não utilizar alguma ferramenta. Porque não usar o melhor de gerenciamento de versão (git) e uma ferramenta que se adequa ao que você precisa? sqitch é o cara nessas horas.</p> +</div> +<div class="section" id="http-www-setupmyproject-com"> +<h2><a class="reference external" href="http://www.setupmyproject.com/">http://www.setupmyproject.com/</a></h2> +<p>Preparação de projetos java, com frameworks, bibliotecas, nomenclatura, etc... Rende uma economia de tempo grandiosa e já vem tudo pronto :).</p> +</div> +<div class="section" id="https-www-pexels-com"> +<h2><a class="reference external" href="https://www.pexels.com/">https://www.pexels.com/</a></h2> +<p>Bom site para imagens free stock. Excelente local para conseguir imagens de alta qualidade.</p> +</div> +<div class="section" id="https-heml-io"> +<h2><a class="reference external" href="https://heml.io/">https://heml.io/</a></h2> +<p>&quot;HEML is an open source markup language for building responsive email.&quot; Melhor descrição impossível.</p> +</div> +<div class="section" id="https-www-mockapi-io"> +<h2><a class="reference external" href="https://www.mockapi.io/">https://www.mockapi.io/</a></h2> +<p>Desenvolva mocks para testar seu front-end. Eles geram inclusive uma carga de dados para ser utilizado nos seus testes.</p> +</div> +<div class="section" id="https-undraw-co"> +<h2><a class="reference external" href="https://undraw.co">https://undraw.co</a></h2> +<p>Needing some cool and free ilustrations? Take a look at it.</p> +</div> +<div class="section" id="https-www-audiotool-com-app"> +<h2><a class="reference external" href="https://www.audiotool.com/app/">https://www.audiotool.com/app/</a></h2> +<p>Ferramenta para criar sons, musicas e afins</p> +</div> +<div class="section" id="https-app-cloudskew-com"> +<h2><a class="reference external" href="https://app.cloudskew.com/">https://app.cloudskew.com/</a></h2> +<p>Desenhar projetos de cloud e afins</p> +</div> +<div class="section" id="https-lottiefiles-com"> +<h2><a class="reference external" href="https://lottiefiles.com/">https://lottiefiles.com/</a></h2> +<p>Veja por si mesmo</p> +</div> +Desenvolvendo apps para o FirefoxOS (Parte 1)2014-09-02T19:00:00-03:002014-09-02T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2014-09-02:/pt/desenvolvendo-app-firefoxos.html<h3>Requisitos mínimos?</h3> +<p>Para seguir este tutorial você precisará do <a href="http://nodejs.org/">Nodejs</a>. Utilizaremos ele para automatizar algumas tarefas, como a criação do nosso projeto e até mesmo o empacotamento da app. Estas automatizações se darão pela utilização de algumas aplicações como o <a href="http://yeoman.io/">Yeoman</a> e o <a href="http://gruntjs.com/">Grunt</a> .</p> +<p>Também será necessário o emulador do …</p><h3>Requisitos mínimos?</h3> +<p>Para seguir este tutorial você precisará do <a href="http://nodejs.org/">Nodejs</a>. Utilizaremos ele para automatizar algumas tarefas, como a criação do nosso projeto e até mesmo o empacotamento da app. Estas automatizações se darão pela utilização de algumas aplicações como o <a href="http://yeoman.io/">Yeoman</a> e o <a href="http://gruntjs.com/">Grunt</a> .</p> +<p>Também será necessário o emulador do <a href="https://www.mozilla.org/pt-BR/firefox/os/">FirefoxOS</a>, ele roda através do seu navegador Firefox. Para instalá-lo basta ir no menu <code>Ferramentas &gt; Desenvolvedor web &gt; App Manager</code>, nesta tela basta tentar iniciar o emulador, se não possuir um já instalado, você será solicitado a fazê-lo. Neste tutorial irei utilizar a versão 1.4.</p> +<h3>Preparando o ambiente</h3> +<p>Tendo o Node instalado, vamos instalar o yeoman e o gerador de app para Firefox OS. Atenção para o parâmetro '-g' no processo de instalação, com ele os seus pacotes serão instalados globalmente, e não só para a pasta em que esta o prompt.</p> +<div class="highlight"><pre><span></span><code><span class="err">npm install -g yo</span> +<span class="err">npm install -g generator-firefoxos-app</span> +</code></pre></div> + +<p>Com ambos os pacotes acima instalados, vamos dar início a criação da app. No seu diretório de projetos ou onde desejar criar a app chama o generator instalado.</p> +<div class="highlight"><pre><span></span><code><span class="err">yo firefoxos-app</span> +</code></pre></div> + +<p>Uma vez chamado esse generator, o mesmo irá fazer alguns questionamentos, o primeiro é claro será o nome da sua aplicação, seguido da descrição e o nome do desenvolvedor.</p> +<p>Após a execução do generator, você já terá uma estrutura para desenvolvimento pronta, inclusive com um html inicial, com todas as dependências já instaladas. Vale ressaltar agora algumas tarefas disponíveis no Gruntfile.</p> +<ul> +<li>Default: Irá gerar o pacote de distribuição</li> +<li>Test: Até a presente versão do generator (0.1.3) este processo irá simplesmente rodar o validador jsHint</li> +<li>Server: Irá disponibilizar na porta 9001 um simples servidor para testar a sua app</li> +</ul> +<p>Vamos testar a nossa app. Para tal, rode o comando <code>grunt server</code> e acesse no seu navegador <code>localhost:9001</code> e devemos ver a seguinte app. Caso nenhuma página seja exibida, revise os passos ateriores e verifique se nenhum erro ocorreu.</p> +<p><img alt="App inicial" src="/images/app_inicial.png"></p> +<p>Vale ressaltar que a sua app toda estará dentro de uma pasta também chamada <code>app</code>. Nela você encontrará os seus arquivos .html, .js, .css e demais. Antes de começarmos a codificar a nossa app, vamos ver como se instala a mesma.</p> +<h3>Instalando a app</h3> +<p>Para fins de teste, não é necessário rodar o comando <code>grunt</code>, sendo que ele irá testar o JS e compactar tudo em um arquivo .zip, basta apontar a instalação para a pasta <code>app</code> dentro do seu projeto. "Mas como eu faço isto?".</p> +<p>Indo novamente na <code>App Manager</code>, clicando na lateral esquerda, onde indica "Aplicativos", teremos então disponível no inferior da tela duas opções, vamos nos ater a utilizar a primeira (<code>Adicionar aplicativo hospedado</code>).</p> +<p>Clicando nesta opção vamos navegar até a pasta da app e clicar selecionada. Pronto.</p> +<p>Simples de se instalar, não acha? O Resultado final deve ser semelhante ao abaixo.</p> +<p><img alt="App inicial" src="/images/app_visual_1.png"></p> +<h3>Acessando uma API</h3> +<p>Quando vamos programar algo mais complexo, geralmente vamos utilizar algo como, câmera, rede, lista de contatos, armazenamento e outras possibilidades. Para utilizarmos essas APIs, precisamos - assim como no desenvolvimento para android - especificar para o usuário no momento de instalação. Estes dados de acesso ficam no arquivo <code>manifes.webapp</code>, se você ainda não deu uma olhada neste arquivo, é nele que fica armazenado dados da app, como nome, descrição, versão, localização de ícones e é claro as permissões que a mesma requer.</p> +<p>As permissões ficam na propriedade permissions, na forma de <code>"chave" : True</code>. Algumas das apis são:</p> +<ul> +<li>câmera</li> +<li>contacts</li> +<li>desktop-notification</li> +<li>storage</li> +</ul> +<p>Cada permissão vai mudar o tipo de app que você esta desenvolvendo, mas aí eu sugiro ler mais na MDN <a href="https://developer.mozilla.org/en-US/Apps/Build/App_permissions">aqui</a>. Esse é o básico para iniciar no desenvolvimento de app para FirefoxOS. Na parte dois, vou começar a passar um pouco de código.</p>Editando o Admin do Django2014-05-15T18:00:00-03:002014-05-15T18:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2014-05-15:/pt/editando-o-admin-do-django.html<p>Este artigo foi re-postado no grupo <a class="reference external" href="http://pythonclub.com.br/editando-o-admin-do-django.html">PythonClub</a>. Vamos falar um pouco sobre como customizar o admin do Django. Primeiramente porque? A resposta é bem simples, quero mostrar algo para o usuário sem que ele precise entrar nas apps e fazer alguma consulta para então tomar alguma ação. Alguns exêmplos para …</p><p>Este artigo foi re-postado no grupo <a class="reference external" href="http://pythonclub.com.br/editando-o-admin-do-django.html">PythonClub</a>. Vamos falar um pouco sobre como customizar o admin do Django. Primeiramente porque? A resposta é bem simples, quero mostrar algo para o usuário sem que ele precise entrar nas apps e fazer alguma consulta para então tomar alguma ação. Alguns exêmplos para isto seriam:</p> +<blockquote> +<ul class="simple"> +<li>Exibir as vendas do mês em forma de gráfico por região do país</li> +<li>Exibir os últimos comentários adicionados</li> +<li>Exibir log dos ultimos usuários cadastrados</li> +</ul> +</blockquote> +<p>O que faremos aqui será exibir os últimos comentários ainda não liberados de um sistema de blog. Vale lembrar que aqui não discutiremos sobre os primeiros passos da aplicação. Para seguirmos adiante, vamos assumir que já temos um projeto básico com uma estrutura simples, abaixo a estrutura inicial do nosso projeto.</p> +<div class="highlight"><pre><span></span>../blog/ +├── core +│ ├── __init__.py +│ ├── admin.py +│ ├── models.py +│ ├── tests.py +│ └── views.py +├── blog +│ ├── __init__.py +│ ├── settings.py +│ ├── urls.py +│ └── wsgi.py +└── manage.py +</pre></div> +<p>Para iniciarmos, precisamos da nossa tabela de comentários, vamos usar a mais simples e básica o possível.</p> +<table border="1" class="docutils"> +<colgroup> +<col width="50%" /> +<col width="50%" /> +</colgroup> +<thead valign="bottom"> +<tr><th class="head">Campo</th> +<th class="head">Tipo</th> +</tr> +</thead> +<tbody valign="top"> +<tr><td>nome</td> +<td>Varchar(30)</td> +</tr> +<tr><td>texto</td> +<td>Text</td> +</tr> +<tr><td>liberado</td> +<td>Boolean</td> +</tr> +<tr><td>data</td> +<td>Date</td> +</tr> +</tbody> +</table> +<p>Vamos seguir adiante e alterar a página inicial do admin para listar os últimos comentários de um simples sistema de blog. Para comerçar a editar o admin, precisamos inicialmente copiar o template que desejamos para a pasta uma pasta <cite>admin</cite> dentro ta pasta de templates do nosso projeto. Isto porque o Admin, não passa de uma app como outra qualquer, portanto o sistema de herança vai funcionar aqui, carregamento prioritariamente o seu template. Você pode conseguir o template que desejar (no nosso caso o index.html) dentro do projeto do Django mesmo, no meu caso &quot;C:\Django-1.6.3\django\contrib\admin\templates\admin&quot;.</p> +<div class="highlight"><pre><span></span>../blog/ +├── templates +│ ├── admin +│ │ └── index.html +├── core +</pre></div> +<p>Tire um tempo e brinque um pouco com este template e veja o que acontece se você alterar algumas coisa. Para adicionarmos a nossa listagem, vamos adicionar um painel lateral, para tal vamos adicionar o código abaixo antes do fechamento da ultima tag div. Nele podemos ver uma chamada para uma template_tag, portanto precisamos carrega-la no topo do template.</p> +<div class="highlight"><pre><span></span>{% load comentarios_tag %} +... +... +... +<span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">&quot;module&quot;</span> <span class="na">id</span><span class="o">=</span><span class="s">&quot;ultimos-comentarios&quot;</span><span class="p">&gt;</span> + <span class="p">&lt;</span><span class="nt">h2</span><span class="p">&gt;</span>Ultimos Comentários<span class="p">&lt;/</span><span class="nt">h2</span><span class="p">&gt;</span> + <span class="p">&lt;</span><span class="nt">h3</span><span class="p">&gt;</span>Liberar<span class="p">&lt;/</span><span class="nt">h3</span><span class="p">&gt;</span> + {% comentarios_n_liberados %} +<span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span> +</pre></div> +<p>Esta template trata-se da responsável por fazer a consulta na base de dados e renderizar a nossa lista, portanto ela é uma 'inclusion tag'. Se você não esta familiarizado com 'template tags', talvez queira dar uma olhada na <a class="reference external" href="https://docs.djangoproject.com/en/dev/howto/custom-template-tags/">documentação do django</a>.</p> +<p>Vamos então criar nossa template tag 'comentarios_n_liberados'. Primeiro devemos criar uma pasta chamada templatetags, dentro da nossa app core. Dentro ta pasta vamos inicializar um pacote python e criar o arquivo comentarios_tag.py. Nele precisamos declarar nosso metodo que deve se chamar 'comentarios_n_liberados' e nele fazer uma simples consulta ao banco buscando os comentários não liberados e por fim registrar a tag apontando para o template que será renderizado. Abaixo o código mais explicado.</p> +<div class="livros"> + <div class="recomendacoes">Recomendações</div> + <a rel="noopener nofollow" href="https://www.amazon.com.br/gp/product/8575225081/ref=as_li_ss_il?ie=UTF8&linkCode=li2&tag=sipmann-20&linkId=c17fa3ac84e734741a3761e874d7d286" target="_blank"><img border="0" src="//ws-na.amazon-adsystem.com/widgets/q?_encoding=UTF8&ASIN=8575225081&Format=_SL160_&ID=AsinImage&MarketPlace=BR&ServiceVersion=20070822&WS=1&tag=sipmann-20" ></a><img src="https://ir-br.amazon-adsystem.com/e/ir?t=sipmann-20&l=li2&o=33&a=8575225081" alt="Livro Pense em Python na Amazon" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /> + <a rel="noopener nofollow" href="https://www.amazon.com.br/gp/product/B074ZTLKHB/ref=as_li_ss_il?ie=UTF8&linkCode=li2&tag=sipmann-20&linkId=e2f37c07da2dc4111ae47854b205d01a" target="_blank"><img border="0" src="//ws-na.amazon-adsystem.com/widgets/q?_encoding=UTF8&ASIN=B074ZTLKHB&Format=_SL160_&ID=AsinImage&MarketPlace=BR&ServiceVersion=20070822&WS=1&tag=sipmann-20" ></a><img src="https://ir-br.amazon-adsystem.com/e/ir?t=sipmann-20&l=li2&o=33&a=B074ZTLKHB" alt="Livro Curso Intensivo de Python na Amazon" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /> +</div><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django</span> <span class="kn">import</span> <span class="n">template</span> +<span class="kn">from</span> <span class="nn">core</span> <span class="kn">import</span> <span class="n">models</span> + +<span class="c1">#Carrega o registro de template tags</span> +<span class="n">register</span> <span class="o">=</span> <span class="n">template</span><span class="o">.</span><span class="n">Library</span><span class="p">()</span> + +<span class="c1">#Registra o metodo a seguir como uma inclusion_tag indicando o template a ser renderizad</span> +<span class="nd">@register</span><span class="o">.</span><span class="n">inclusion_tag</span><span class="p">(</span><span class="s1">&#39;comentarios_n_liberados.html&#39;</span><span class="p">)</span> +<span class="k">def</span> <span class="nf">comentarios_n_liberados</span><span class="p">():</span> + <span class="n">comentarios</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">comentario</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">liberado</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span><span class="o">.</span><span class="n">order_by</span><span class="p">(</span><span class="s1">&#39;data&#39;</span><span class="p">)[</span><span class="mi">0</span><span class="p">:</span><span class="mi">5</span><span class="p">]</span> + <span class="k">return</span> <span class="p">{</span> <span class="s1">&#39;comentarios&#39;</span> <span class="p">:</span> <span class="n">comentarios</span> <span class="p">}</span> +</pre></div> +<p>Abaixo o html do nosso template a ser renderizado, este deve estar dentro da pasta templates da nossa app core.</p> +<div class="highlight"><pre><span></span>{% if not comentarios %} + <span class="p">&lt;</span><span class="nt">p</span><span class="p">&gt;</span>Nenhum comentário novo<span class="p">&lt;/</span><span class="nt">p</span><span class="p">&gt;</span> +{% else %} + <span class="p">&lt;</span><span class="nt">ul</span><span class="p">&gt;</span> + {% for c in comentarios %} + <span class="p">&lt;</span><span class="nt">li</span> <span class="na">class</span><span class="o">=</span><span class="s">&quot;addlink&quot;</span><span class="p">&gt;</span> + <span class="p">&lt;</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">&quot;{{ c.id }}&quot;</span><span class="p">&gt;</span>{{ c.texto|truncatechars:30 }}<span class="p">&lt;/</span><span class="nt">a</span><span class="p">&gt;</span> + <span class="p">&lt;/</span><span class="nt">li</span><span class="p">&gt;</span> + {% endfor %} + <span class="p">&lt;/</span><span class="nt">ul</span><span class="p">&gt;</span> +{% endif %} +</pre></div> +<p>Com tudo isto feito, basta subir o seu servidor e ver o resultado final, que pode ser visto na imagem abaixo.</p> +<img alt="Resultado final" src="images/admin_modificado.png" /> +<p>Lembrando que aqui apenas mostrei como modificar o index do admin, para apenas listar dados do banco, mas você pode ir muito mais além. Abaixo fica a estrutura de diretórios final e um link para download do projeto funcionando.</p> +<div class="highlight"><pre><span></span>../blog/ +├── core +│ ├── templates +│ │ └── comentarios_n_liberados.html +│ ├── templatetag +│ │ └── comentarios_tag.py +│ ├── __init__.py +│ ├── admin.py +│ ├── models.py +│ ├── tests.py +│ └── views.py +├── blog +│ ├── __init__.py +│ ├── settings.py +│ ├── urls.py +│ └── wsgi.py +├── templates +│ ├── admin +│ │ └── index.html +└── manage.py +</pre></div> +<p>Espero que tenham gostado, criticas/sugestões são bem-vindas. <a class="reference external" href="https://github.com/sipmann/editando-django-admin">Fontes do Projeto</a></p> + \ No newline at end of file diff --git a/pt/feeds/mauricio-camargo-sipmann.atom.xml.gz b/pt/feeds/mauricio-camargo-sipmann.atom.xml.gz new file mode 100644 index 000000000..767d0fae3 Binary files /dev/null and b/pt/feeds/mauricio-camargo-sipmann.atom.xml.gz differ diff --git a/pt/feeds/mauricio-camargo-sipmann.rss.xml b/pt/feeds/mauricio-camargo-sipmann.rss.xml new file mode 100644 index 000000000..89c059dc4 --- /dev/null +++ b/pt/feeds/mauricio-camargo-sipmann.rss.xml @@ -0,0 +1,30 @@ + +Sipmann - Maurício Camargo Sipmannhttps://www.sipmann.com/pt/Mon, 21 Dec 2020 13:30:00 -0300Monitorando restarts do MySQL com PowerShellhttps://www.sipmann.com/pt/monitoring-mysql-restarts-with-powershell.html<p>Bom, chegou a hora para mais um script PowerShell. Se você ainda não viu os outros, de uma olhada no link abaixo.</p> +<ul> +<li><a href="https://www.sipmann.com/pt/monitoring-mysql-replication-with-powershell.html">Monitorando status de replicação do MySQL com PowerShell</a></li> +</ul> +<p>Este aqui é um script bem simples, mas novamente, se seu cliente não possui um servidor Zabbix ou não permite …</p>Maurício Camargo SipmannMon, 21 Dec 2020 13:30:00 -0300tag:www.sipmann.com,2020-12-21:/pt/monitoring-mysql-restarts-with-powershell.htmlPowerShellMySQLMySQL RestartPowershell monitoringTrocando a senha de um usuário do MySQL sem downtime da aplicaçãohttps://www.sipmann.com/pt/mysql-dual-password-functionality.html<p>Você deseja trocar a senha de um usuário do MySQL que está sendo utilizado por uma aplicação e não sofrer nenhum downtime? Bom, a versão 8.0.14 do MySQL foi liberada com uma feature chamada <a href="https://dev.mysql.com/doc/refman/8.0/en/password-management.html#dual-passwords">Dual Password Support</a>, com esta feature você pode alterar a senha de um usuário …</p>Maurício Camargo SipmannWed, 09 Dec 2020 13:40:00 -0300tag:www.sipmann.com,2020-12-09:/pt/mysql-dual-password-functionality.htmlMySQLMySQLMySQL Dual PasswordApache Nifi JSON to SQL removendo underlinehttps://www.sipmann.com/pt/apache-nifi-json-to-sql-replacing-underscore.html<p>Recentemente eu estava desenvolvendo alguns processos de ETL com o Apache NiFi. Mas após alguns minutos desenhando o meu fluxo, eu vi um comportamento estranho do componente ConvertJSONToSQL, que estava substituindo os underline ('_') do nome de um campo utilizado na condição da SQL (eu estava preparando um UPDATE). Aquilo …</p>Maurício Camargo SipmannWed, 02 Dec 2020 14:00:00 -0300tag:www.sipmann.com,2020-12-02:/pt/apache-nifi-json-to-sql-replacing-underscore.htmlToolsApache NifiConvertJSONToSQLremovendo underlineBloqueando um usuário do SQL Server baseado em uma tabela de horárioshttps://www.sipmann.com/pt/blocking-user-on-sql-server-based-on-schedule.html<p>Ok, algum tempo atrás, eu postei sobre como você pode impor limites às conexões do SQL Server utilizando o <a href="https://www.sipmann.com/limiting-connection-resources-sql-server.html#.X6Cz8IhKhPY">Resource Governor</a>. Mas, e se você não pode utilizar ele? Você sempre pode bloquear logins usando uma trigger, mas eu não gosto da ideia de ter um select rodando a cada …</p>Maurício Camargo SipmannSat, 14 Nov 2020 07:00:00 -0300tag:www.sipmann.com,2020-11-14:/pt/blocking-user-on-sql-server-based-on-schedule.htmlSQL ServerSQLServerUserTime Schedule blockingComo definir as colunas no select utilizando Entity Frameworkhttps://www.sipmann.com/pt/select_specific_fields_with_efcore.html<p>Então, você utiliza Entity Framework Core e geralmente faz o seu selecto da seguinte forma, talvez você está retornando muitos dados.</p> +<div class="highlight"><pre><span></span><code><span class="kt">var</span> <span class="n">products</span> <span class="p">=</span> <span class="n">Products</span> + <span class="p">.</span><span class="n">Where</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span> <span class="p">&gt;</span> <span class="m">0</span><span class="p">)</span> + <span class="p">.</span><span class="n">OrderBy</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">)</span> + <span class="p">.</span><span class="n">ToList</span><span class="p">()</span> +</code></pre></div> + +<p>Rodando a query acima, em uma base de testes você obtem o seguinte resultado, veja quantas …</p>Maurício Camargo SipmannWed, 28 Oct 2020 19:00:00 -0300tag:www.sipmann.com,2020-10-28:/pt/select_specific_fields_with_efcore.html.NETDotNetDotNet CoreEntity FrameworkEF CoreSpecify columnsZabbix Running on Low Memory Modehttps://www.sipmann.com/pt/zabbix-running-on-low-memory-mode.html<p>Olá pessoal! Trago hoje outro post sobre Zabbix. Este é sobre aumentar o cache do seu Zabbix Server. É perfeitamente comum (se você roda com as configurações padrões) receber avisos sobre <code>Zabbix value cache running on low memory mode</code> no seu dashboard ou arquivos de log.</p> +<p><img alt="Zabbix Dashboard alertando sobre problemas de memória" src="/images/zabbix_low_memory_mode.png"> +<img alt="Zabbix Dashboard cache gráfico com 70% utilizado" src="/images/zabbix_cache_filling.png"></p> +<p>Para resolver, abra o …</p>Maurício Camargo SipmannTue, 20 Oct 2020 19:00:00 -0300tag:www.sipmann.com,2020-10-20:/pt/zabbix-running-on-low-memory-mode.htmlLinuxZabbixShellLow memoryCacheMonitorando status de replicação do MySQL com PowerShellhttps://www.sipmann.com/pt/monitoring-mysql-replication-with-powershell.html<p>Tenho migrado alguns scripts bash que tenho para PowerShell, e chegou a vez de migrar um script de monitoramento de replicação do MySQL. Fica como crédito o script original do <a href="https://handyman.dulare.com/mysql-replication-status-alerts-with-bash-script/">Paweł</a>. É um script bem simples onde eu verifico algumas tags resultantes do <code>SHOW SLAVE STATUS\G</code>, são elas. <code>Slave_IO_Running …</code></p>Maurício Camargo SipmannWed, 14 Oct 2020 19:00:00 -0300tag:www.sipmann.com,2020-10-14:/pt/monitoring-mysql-replication-with-powershell.htmlPowerShellMySQLMySQL ReplicationPowerShellPowershell mailMicrosoft Contra Covidhttps://www.sipmann.com/pt/microsoft-against-covid.html<p>Você teve seu trabalho afetado pela pandemia do covid? Bom, na última semana eu postei no <a href="https://grepora.com/2020/09/17/microsoft-ignite-certification-voucher/">Grepora</a> sobre um Voucher para certificação gratuita que a Microsoft estava distribuindo durante o evento Microsoft Ignite. Depois disto, eu fiquei sabendo que eles também estão entregando grandes discontos para quem teve o seu …</p>Maurício Camargo SipmannSat, 03 Oct 2020 19:00:00 -0300tag:www.sipmann.com,2020-10-03:/pt/microsoft-against-covid.htmlAzureAzureCertificationMicrosoftO poder do PowerShellhttps://www.sipmann.com/pt/the-power-of-powershell.html<p>Como um usuário linux por muito tempo, eu automatizei algumas tarefas com scripts bash e fiquei longe do PowerShell... Voltei a utilizar Windows alguns anos atrás e ainda assim, não dei uma chance ao PS. Mas porque não? Eu fiz alguns scripts para automatizar algumas tarefas em um servidor Protheus …</p>Maurício Camargo SipmannMon, 21 Sep 2020 19:00:00 -0300tag:www.sipmann.com,2020-09-21:/pt/the-power-of-powershell.htmlPowerShellAzurePowerShellScriptGetChild-ItemRemove-ItemStop-ProccessTop Level Statement no C# 9https://www.sipmann.com/pt/top_level_statement_csharp_9.html<p>Olá pessoal, venho hoje falar sobre uma novidade que estará disponível na versão 9 do C#. Toda vez que você deseja criar um novo projeto, você sempre tem o mesmo arquivo Main, com a mesma estrutura. Na próxima versão do C# (versão 9), nós teremos uma nova funcionalidade chamada <code>Top …</code></p>Maurício Camargo SipmannWed, 29 Jul 2020 19:00:00 -0300tag:www.sipmann.com,2020-07-29:/pt/top_level_statement_csharp_9.html.NETC#Dotnet CoreDotNet.netZabbix poller processes more than 75%https://www.sipmann.com/pt/zabbix-poller-processes-more-than-75.html<p>Este é o terceiro post sobre configurações para o Zabbix. Todas as alterações que eu sugiro nestes posts, são baseadas em um servidor com 50+ hosts. Outro problema que pode ocorrer em seu servidor, é o poller de informações ficar sobrecarregado pela quantidade de servidores que ele precisa pegar carga …</p>Maurício Camargo SipmannThu, 02 Jul 2020 19:00:00 -0300tag:www.sipmann.com,2020-07-02:/pt/zabbix-poller-processes-more-than-75.htmlLinuxZabbixShellZabbix PollerPoller proccessMonitorando a disponibilidade de um Website com Azure Functionshttps://www.sipmann.com/pt/monitoring-website-heath-with-azure-functions.html<p>Algumas vezes você se depara com a necessidade de monitorar a disponibilidade de um website ou mudanças em seu conteúdo. É claro que temos diversas opções disponíveis no mercado, mas para fins de curiosidade, vamos programar o nosso próprio e ver o que podemos fazer. Primeiramente, tudo que você ver …</p>Maurício Camargo SipmannMon, 22 Jun 2020 19:00:00 -0300tag:www.sipmann.com,2020-06-22:/pt/monitoring-website-heath-with-azure-functions.htmlAzureAzureAzure DevopsC#Dotnet CoreDotNetMonitor WebsiteZabbix ICMP pinger processes more than 75%https://www.sipmann.com/pt/zabbix-icmp-pinger-processes-more-than-75.html<p>Então o seu systema de monitoramento creasceu e o seu Zabbix começou a printar "<em>Zabbix icmp pinger processes more than 75% busy</em>" no seu dashboard.</p> +<p><img alt="Dashboard do zabbix avisando sobre o erro" src="/images/zabbix_pinger01.png"></p> +<p>Tudo que você tem a fazer é abrir o seu arquivo de configuração (<code>/etc/zabbix/zabbix_server.conf</code>) e localizar a tag chamada <code>StartPingers</code>. Ela deve …</p>Maurício Camargo SipmannMon, 25 May 2020 16:00:00 -0300tag:www.sipmann.com,2020-05-25:/pt/zabbix-icmp-pinger-processes-more-than-75.htmlLinuxZabbixicmp pingericmp pinger more than 75Zabbix ServerZabbix Server Out of Memoryhttps://www.sipmann.com/pt/zabbix-server-out-of-memory-crash.html<p>Você tem um servidor Zabbix crashando e observando o arquivo de log <code>/var/log/zabbix/zabbix_server.log</code> você localiza a seguinte mensagem referênciando falta de memória?</p> +<div class="highlight"><pre><span></span><code>__mem_malloc: skipped <span class="m">0</span> asked <span class="m">24</span> skip_min <span class="m">18446744073709551615</span> skip_max <span class="m">0</span> +<span class="o">[</span>file:dbconfig.c,line:94<span class="o">]</span> __zbx_mem_realloc<span class="o">()</span>: out of memory <span class="o">(</span>requested <span class="m">16</span> bytes<span class="o">)</span> +<span class="o">[</span>file:dbconfig.c …</code></pre></div>Maurício Camargo SipmannThu, 27 Feb 2020 19:00:00 -0300tag:www.sipmann.com,2020-02-27:/pt/zabbix-server-out-of-memory-crash.htmlLinuxZabbixShellOut of memoryCrashRemovendo um usuário de uma base SQL Serverhttps://www.sipmann.com/pt/removing-user-from-sql-server-database.html<p>O seu cliente lhe pede com urgência para <em>dropar</em> um usuário da sua base MsSQL Server, mas você trava com o seguinte aviso de erro:</p> +<div class="highlight"><pre><span></span><code><span class="n">Error</span><span class="o">:</span> <span class="mi">15138</span> <span class="n">The</span> <span class="n">database</span> <span class="n">principal</span> <span class="n">owns</span> <span class="n">a</span> <span class="n">schema</span> <span class="k">in</span> <span class="n">the</span> <span class="n">database</span><span class="o">,</span> <span class="n">and</span> <span class="n">cannot</span> <span class="n">be</span> <span class="n">dropped</span><span class="o">.</span> +</code></pre></div> + +<p>Se você não possui (ou no momento não consegue acesso …</p>Maurício Camargo SipmannFri, 06 Sep 2019 07:00:00 -0300tag:www.sipmann.com,2019-09-06:/pt/removing-user-from-sql-server-database.htmlSQL ServerSQLServerUserThe database principal owns a schemaResolvendo java.net.SocketException: Protocol family unavailable em Java + Docker + WildFlyhttps://www.sipmann.com/pt/socketException-protocol-family-unavailable-java-docker-wildfly.html<p>Nos últimos dias eu estou brincando com o <a class="reference external" href="http://wildfly-swarm.io/">WildFly Swarm</a> e decidi fazer o deploy de uma aplicação simples com Docker. Deveria funcionar bem, ao menos é o que pensava. Construí um container com o seguinte Dockerfile e ao invés de obter uma aplicação web, tudo que eu obtive foi …</p>Maurício Camargo SipmannSun, 04 Mar 2018 17:40:00 -0300tag:www.sipmann.com,2018-03-04:/pt/socketException-protocol-family-unavailable-java-docker-wildfly.htmlJavaJavaWildFlyDockerjava.net.SocketExceptionProtocol family unavailableMenu dinâmico com as apps do djangohttps://www.sipmann.com/pt/menu-dinamico-com-apps-do-django.html<p>Digamos que sua empresa trabalha com Django desenvolvendo aplicações cujas apps são plugaveis e reutilizáveis. Por que não se aproveitar de um certo padrão de desenvolvimento para desenvolver menus que se modificam de acordo com as apps que estão no projeto? Como o objetivo aqui não é desenvolver uma app …</p>Maurício Camargo SipmannSun, 21 Jan 2018 21:17:00 -0200tag:www.sipmann.com,2018-01-21:/pt/menu-dinamico-com-apps-do-django.htmlPythonpythondjangoScripts de inicialização no raspberry pihttps://www.sipmann.com/pt/script-de-inicializacao-raspberry.html<p>Instalei essa semana o <a class="reference external" href="https://gitea.io">gitea</a> no meu raspberry pi B + e queria iniciar ele no boot... Não sou profundo conhecedor de linux, então, logo não sabia como fazer isto da melhor forma. +As versões atuais do Raspbian utilizam o <cite>systemd</cite> para gerenciar os serviços e confesso que nunca havia utilizado …</p>Maurício Camargo SipmannSun, 08 Oct 2017 18:00:00 -0300tag:www.sipmann.com,2017-10-08:/pt/script-de-inicializacao-raspberry.htmlShellShellraspberryCool Toolshttps://www.sipmann.com/pt/cool-tools.html<p>Com o passar do tempo você vai &quot;encontrando&quot; - e às vezes até mesmo desenvolvendo - algumas ferramentas que tornam o seu dia a dia como desenvolvedor mais fácil. Abaixo seguem algumas das minhas ferramentas que costumo usar. Ressalto que essa lista será (provavelmente) atualizada com o passar do tempo.</p> +<div class="section" id="https-www-gitkraken-com"> +<h2><a class="reference external" href="https://www.gitkraken.com">https://www …</a></h2></div>Maurício Camargo SipmannSun, 17 Sep 2017 14:00:00 -0300tag:www.sipmann.com,2017-09-17:/pt/cool-tools.htmlToolsToolsDesenvolvendo apps para o FirefoxOS (Parte 1)https://www.sipmann.com/pt/desenvolvendo-app-firefoxos.html<h3>Requisitos mínimos?</h3> +<p>Para seguir este tutorial você precisará do <a href="http://nodejs.org/">Nodejs</a>. Utilizaremos ele para automatizar algumas tarefas, como a criação do nosso projeto e até mesmo o empacotamento da app. Estas automatizações se darão pela utilização de algumas aplicações como o <a href="http://yeoman.io/">Yeoman</a> e o <a href="http://gruntjs.com/">Grunt</a> .</p> +<p>Também será necessário o emulador do …</p>Maurício Camargo SipmannTue, 02 Sep 2014 19:00:00 -0300tag:www.sipmann.com,2014-09-02:/pt/desenvolvendo-app-firefoxos.htmlFirefoxOSFirefoxOSHtmlYeomanEditando o Admin do Djangohttps://www.sipmann.com/pt/editando-o-admin-do-django.html<p>Este artigo foi re-postado no grupo <a class="reference external" href="http://pythonclub.com.br/editando-o-admin-do-django.html">PythonClub</a>. Vamos falar um pouco sobre como customizar o admin do Django. Primeiramente porque? A resposta é bem simples, quero mostrar algo para o usuário sem que ele precise entrar nas apps e fazer alguma consulta para então tomar alguma ação. Alguns exêmplos para …</p>Maurício Camargo SipmannThu, 15 May 2014 18:00:00 -0300tag:www.sipmann.com,2014-05-15:/pt/editando-o-admin-do-django.htmlPythonpythondjangodjango-admin \ No newline at end of file diff --git a/pt/feeds/mauricio-camargo-sipmann.rss.xml.gz b/pt/feeds/mauricio-camargo-sipmann.rss.xml.gz new file mode 100644 index 000000000..84a585619 Binary files /dev/null and b/pt/feeds/mauricio-camargo-sipmann.rss.xml.gz differ diff --git a/pt/feeds/mysql.atom.xml b/pt/feeds/mysql.atom.xml new file mode 100644 index 000000000..9d0ecd0fd --- /dev/null +++ b/pt/feeds/mysql.atom.xml @@ -0,0 +1,14 @@ + +Sipmann - MySQLhttps://www.sipmann.com/pt/2020-12-09T13:40:00-03:00Trocando a senha de um usuário do MySQL sem downtime da aplicação2020-12-09T13:40:00-03:002020-12-09T13:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-12-09:/pt/mysql-dual-password-functionality.html<p>Você deseja trocar a senha de um usuário do MySQL que está sendo utilizado por uma aplicação e não sofrer nenhum downtime? Bom, a versão 8.0.14 do MySQL foi liberada com uma feature chamada <a href="https://dev.mysql.com/doc/refman/8.0/en/password-management.html#dual-passwords">Dual Password Support</a>, com esta feature você pode alterar a senha de um usuário …</p><p>Você deseja trocar a senha de um usuário do MySQL que está sendo utilizado por uma aplicação e não sofrer nenhum downtime? Bom, a versão 8.0.14 do MySQL foi liberada com uma feature chamada <a href="https://dev.mysql.com/doc/refman/8.0/en/password-management.html#dual-passwords">Dual Password Support</a>, com esta feature você pode alterar a senha de um usuário mantendo a anterior ainda funcionando como uma forma de "backup". Desta forma, você ainda conseguirá autenticar com o usuário utilizando tanto a nova senha, quanto a anterior. Com isto, o seu processo de troca de senha fica algo como:</p> +<p>1) Troque a senha mantendo a anterior;</p> +<p>2) Faça o Deploy da nova configuração na sua aplicação/cluster;</p> +<p>3) Descarte a senha anterior.</p> +<p>Para alterar a senha mantendo a anterior, você deve rodar o seguinte comando:</p> +<div class="highlight"><pre><span></span><code><span class="k">ALTER</span> <span class="n">USER</span> <span class="s1">&#39;appuser&#39;</span><span class="o">@</span><span class="s1">&#39;localhost&#39;</span> <span class="n">IDENTIFIED</span> <span class="k">BY</span> <span class="s1">&#39;new_password&#39;</span> <span class="n">RETAIN</span> <span class="n">CURRENT</span> <span class="n">PASSWORD</span><span class="p">;</span> +</code></pre></div> + +<p>Para descartar a senha antiga, rode o seguinte:</p> +<div class="highlight"><pre><span></span><code><span class="k">ALTER</span> <span class="n">USER</span> <span class="s1">&#39;appuser&#39;</span><span class="o">@</span><span class="s1">&#39;localhost&#39;</span> <span class="n">DISCARD</span> <span class="n">OLD</span> <span class="n">PASSWORD</span><span class="p">;</span> +</code></pre></div> + +<p>E pronto. Espero que isto lhe ajude a evitar downtimes e dores de cabeça :)</p> \ No newline at end of file diff --git a/pt/feeds/mysql.atom.xml.gz b/pt/feeds/mysql.atom.xml.gz new file mode 100644 index 000000000..dc27d70e8 Binary files /dev/null and b/pt/feeds/mysql.atom.xml.gz differ diff --git a/pt/feeds/net.atom.xml b/pt/feeds/net.atom.xml new file mode 100644 index 000000000..36541ed3b --- /dev/null +++ b/pt/feeds/net.atom.xml @@ -0,0 +1,59 @@ + +Sipmann - .NEThttps://www.sipmann.com/pt/2020-10-28T19:00:00-03:00Como definir as colunas no select utilizando Entity Framework2020-10-28T19:00:00-03:002020-10-28T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-28:/pt/select_specific_fields_with_efcore.html<p>Então, você utiliza Entity Framework Core e geralmente faz o seu selecto da seguinte forma, talvez você está retornando muitos dados.</p> +<div class="highlight"><pre><span></span><code><span class="kt">var</span> <span class="n">products</span> <span class="p">=</span> <span class="n">Products</span> + <span class="p">.</span><span class="n">Where</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span> <span class="p">&gt;</span> <span class="m">0</span><span class="p">)</span> + <span class="p">.</span><span class="n">OrderBy</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">)</span> + <span class="p">.</span><span class="n">ToList</span><span class="p">()</span> +</code></pre></div> + +<p>Rodando a query acima, em uma base de testes você obtem o seguinte resultado, veja quantas …</p><p>Então, você utiliza Entity Framework Core e geralmente faz o seu selecto da seguinte forma, talvez você está retornando muitos dados.</p> +<div class="highlight"><pre><span></span><code><span class="kt">var</span> <span class="n">products</span> <span class="p">=</span> <span class="n">Products</span> + <span class="p">.</span><span class="n">Where</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span> <span class="p">&gt;</span> <span class="m">0</span><span class="p">)</span> + <span class="p">.</span><span class="n">OrderBy</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">)</span> + <span class="p">.</span><span class="n">ToList</span><span class="p">()</span> +</code></pre></div> + +<p>Rodando a query acima, em uma base de testes você obtem o seguinte resultado, veja quantas colunas estão retornando da sua base de dados.</p> +<p><img alt="Print com todas as colunas" src="/images/ef_core_allcolumns.png"></p> +<p>No meu caso, eu só pretendo ter de volta as colunas Title, PublishedData e uma pequena descrição. Então para selecionar apenas estes campos, nós temos algumas opções. Na primeira, nós vamos definir os campos e retornar um objeto do tipo Dynamic. A segunda forma, é dar ao .NET o objeto a ser retornado, pode ser por exêmplo um DTO.</p> +<div class="highlight"><pre><span></span><code><span class="kt">var</span> <span class="n">products</span> <span class="p">=</span> <span class="n">Products</span> + + <span class="p">.</span><span class="n">Select</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="k">new</span> <span class="p">{</span><span class="n">p</span><span class="p">.</span><span class="n">ProductID</span><span class="p">,</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">,</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span><span class="p">,</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitPrice</span><span class="p">})</span> + <span class="c1">//.Select(p =&gt; new ProductDTO {p.ProductID, p.ProductName, p.UnitsInStock, p.UnitPrice})</span> + + <span class="p">.</span><span class="n">Where</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">UnitsInStock</span> <span class="p">&gt;</span> <span class="m">0</span><span class="p">)</span> + <span class="p">.</span><span class="n">OrderBy</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">ProductName</span><span class="p">)</span> + <span class="p">.</span><span class="n">ToList</span><span class="p">()</span> +</code></pre></div> + +<p><img alt="Print com menos colunas e também menor quantidade de dados" src="/images/ef_core_less_columns.png"></p>Top Level Statement no C# 92020-07-29T19:00:00-03:002020-07-29T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-07-29:/pt/top_level_statement_csharp_9.html<p>Olá pessoal, venho hoje falar sobre uma novidade que estará disponível na versão 9 do C#. Toda vez que você deseja criar um novo projeto, você sempre tem o mesmo arquivo Main, com a mesma estrutura. Na próxima versão do C# (versão 9), nós teremos uma nova funcionalidade chamada <code>Top …</code></p><p>Olá pessoal, venho hoje falar sobre uma novidade que estará disponível na versão 9 do C#. Toda vez que você deseja criar um novo projeto, você sempre tem o mesmo arquivo Main, com a mesma estrutura. Na próxima versão do C# (versão 9), nós teremos uma nova funcionalidade chamada <code>Top Level Statement</code>. Com isto, poderemos programar a nossa aplicação sem toda aquela estrutura de <code>namespace/class/public void static main</code>. Veja o código abaixo.</p> +<div class="highlight"><pre><span></span><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span> + +<span class="n">Console</span><span class="p">.</span><span class="n">WriteLine</span><span class="p">(</span><span class="s">&quot;Hello World!&quot;</span><span class="p">);</span> +</code></pre></div> + +<p>Parece muito simples, não é? Com isto, você pode brincar com seu código e até mesmo programar uma pequena WEB API. Para começar a brincar com estas novas <em>features</em>, primeiramente faça o download do preview do <a href="https://dotnet.microsoft.com/download/dotnet/5.0">.net 5 SDK</a> e modifique o seu arquivo <code>.csproj</code> para apontar o framework para <code>.net5.0</code> e a versão de preview da linguagem. Abaixo como uma aplicação de console deve ficar.</p> +<div class="highlight"><pre><span></span><code><span class="nt">&lt;Project</span> <span class="na">Sdk=</span><span class="s">&quot;Microsoft.NET.Sdk&quot;</span><span class="nt">&gt;</span> + <span class="nt">&lt;PropertyGroup&gt;</span> + <span class="nt">&lt;OutputType&gt;</span>Exe<span class="nt">&lt;/OutputType&gt;</span> + <span class="nt">&lt;TargetFramework&gt;</span>net5.0<span class="nt">&lt;/TargetFramework&gt;</span> + <span class="nt">&lt;LangVersion&gt;</span>preview<span class="nt">&lt;/LangVersion&gt;</span> + <span class="nt">&lt;/PropertyGroup&gt;</span> +<span class="nt">&lt;/Project&gt;</span> +</code></pre></div> + +<p>E assim você está pronto para brincar com as novas funcionalidades que estão disponíveis na versão preview. Vamos programar uma aplicação simples que faz uma requisição na API da NASA e printe a Imagem do Dia no console. Não é nenhum código mirabolante, é simplesmente para exemplificar o quão simples uma simples chamada de API pode ser. Feito isto, porque não salvar a imagem como um arquivo? Ou então enviar essa imagem via telegram?</p> +<div class="highlight"><pre><span></span><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Net.Http</span><span class="p">;</span> +<span class="k">using</span> <span class="nn">System.Text.Json</span><span class="p">;</span> + +<span class="kt">var</span> <span class="n">API</span> <span class="p">=</span> <span class="s">&quot;https://api.nasa.gov/planetary/apod?hd=true&amp;api_key=DEMO_KEY&quot;</span><span class="p">;</span> +<span class="kt">var</span> <span class="n">cli</span> <span class="p">=</span> <span class="k">new</span> <span class="n">HttpClient</span><span class="p">();</span> + +<span class="kt">var</span> <span class="n">response</span> <span class="p">=</span> <span class="k">await</span> <span class="n">cli</span><span class="p">.</span><span class="n">GetAsync</span><span class="p">(</span><span class="n">API</span><span class="p">);</span> +<span class="kt">var</span> <span class="n">data</span> <span class="p">=</span> <span class="n">JsonSerializer</span><span class="p">.</span><span class="n">Deserialize</span><span class="p">&lt;</span><span class="n">NasaApi</span><span class="p">&gt;(</span><span class="k">await</span> <span class="n">response</span><span class="p">.</span><span class="n">Content</span><span class="p">.</span><span class="n">ReadAsStringAsync</span><span class="p">());</span> + +<span class="n">Console</span><span class="p">.</span><span class="n">WriteLine</span><span class="p">(</span><span class="n">data</span><span class="p">.</span><span class="n">Url</span><span class="p">);</span> +</code></pre></div> + +<p>Por hoje é isso. Fique de olho nas novas features que o C# 9 vai nos trazer. Já temos várias disponíveis hoje para testar, esta é apenas uma delas.</p> \ No newline at end of file diff --git a/pt/feeds/net.atom.xml.gz b/pt/feeds/net.atom.xml.gz new file mode 100644 index 000000000..7ea3ecdce Binary files /dev/null and b/pt/feeds/net.atom.xml.gz differ diff --git a/pt/feeds/powershell.atom.xml b/pt/feeds/powershell.atom.xml new file mode 100644 index 000000000..3ae913d80 --- /dev/null +++ b/pt/feeds/powershell.atom.xml @@ -0,0 +1,124 @@ + +Sipmann - PowerShellhttps://www.sipmann.com/pt/2020-12-21T13:30:00-03:00Monitorando restarts do MySQL com PowerShell2020-12-21T13:30:00-03:002020-12-21T13:30:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-12-21:/pt/monitoring-mysql-restarts-with-powershell.html<p>Bom, chegou a hora para mais um script PowerShell. Se você ainda não viu os outros, de uma olhada no link abaixo.</p> +<ul> +<li><a href="https://www.sipmann.com/pt/monitoring-mysql-replication-with-powershell.html">Monitorando status de replicação do MySQL com PowerShell</a></li> +</ul> +<p>Este aqui é um script bem simples, mas novamente, se seu cliente não possui um servidor Zabbix ou não permite …</p><p>Bom, chegou a hora para mais um script PowerShell. Se você ainda não viu os outros, de uma olhada no link abaixo.</p> +<ul> +<li><a href="https://www.sipmann.com/pt/monitoring-mysql-replication-with-powershell.html">Monitorando status de replicação do MySQL com PowerShell</a></li> +</ul> +<p>Este aqui é um script bem simples, mas novamente, se seu cliente não possui um servidor Zabbix ou não permite que você configure um para realizar este monitoramento, um conjunto de scripts pode ser bem útil. Primeiramente nós executamos uma query báscia <code>SHOW GLOBAL STATUS LIKE 'Uptime'</code>, com ela nós conseguimos capturar exatamente o que nós estamos procurando.</p> +<p>Se por alguma razão o comando falhar (verificamos atravez da variábel global <code>$lastExitCode</code>), nós mandamos um e-mail lhe avisando sobre o problema ocorrido.</p> +<p>E então, nós chegamos à parte onde fazemos o parse do valor obtido, esta parte é bem similar ao parse que codificamos no primeiro post sobre monitoramento utilizando PowerShell. Nós basicamentes procuramos pela linha contendo <code>Value</code>, separamos por espaço e então parseamos a segunda posição em um inteiro. Então tudo que precisamos fazer é verificar se o valor parseado é menor que o nosso threshold, se for menor, nós mandamos um e-mail.</p> +<div class="highlight"><pre><span></span><code><span class="nv">$MailFrom</span> <span class="p">=</span> <span class="s1">&#39;maurio[at]sipmann.com&#39;</span> +<span class="nv">$MailTo</span> <span class="p">=</span> <span class="s1">&#39;mauricio[at]sipmann.com&#39;</span> +<span class="nv">$MysqlHost</span> <span class="p">=</span> <span class="s1">&#39;127.0.0.1&#39;</span> +<span class="nv">$MysqlUser</span> <span class="p">=</span> <span class="s1">&#39;root&#39;</span> +<span class="nv">$MysqlPass</span> <span class="p">=</span> <span class="s1">&#39;123&#39;</span> + + +<span class="nv">$data</span> <span class="p">=</span> <span class="p">$(</span><span class="n">mysql</span> <span class="n">-h</span> <span class="nv">$MysqlHost</span> <span class="n">-u</span> <span class="nv">$MysqlUser</span> <span class="n">-p</span><span class="s2">&quot;$MysqlPass&quot;</span> <span class="n">-e</span> <span class="s2">&quot;SHOW GLOBAL STATUS LIKE &#39;Uptime&#39; \G&quot;</span><span class="p">)</span> + +<span class="cm">&lt;# Unable to execute the sql Command #&gt;</span> +<span class="k">if</span> <span class="p">(</span><span class="nv">$lastExitCode</span> <span class="o">-eq</span> <span class="n">1</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Send-MailMessage</span> <span class="n">-To</span> <span class="nv">$MailTo</span> <span class="n">-From</span> <span class="nv">$MailFrom</span> <span class="n">-Subject</span> <span class="s1">&#39;Connection problem&#39;</span> <span class="n">-bodyAsHtml</span> <span class="s2">&quot;Connection problem on host ${MysqlHost}&quot;</span> <span class="n">-Credential</span> <span class="nb">Get-Credential</span> <span class="n">-SmtpServer</span> <span class="s1">&#39;smtp.office365.com&#39;</span> <span class="n">-Port</span> <span class="n">587</span> <span class="n">-UseSsl</span> + <span class="n">exit</span> +<span class="p">}</span> + +<span class="nv">$UpTime</span> <span class="p">=</span> <span class="no">[int]</span><span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Value:&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> + +<span class="cm">&lt;# If the uptime is lower then 20 minutes #&gt;</span> +<span class="k">if</span> <span class="p">(</span><span class="nv">$UpTime</span> <span class="o">-lt</span> <span class="n">1200</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Send-MailMessage</span> <span class="n">-To</span> <span class="nv">$MailTo</span> <span class="n">-From</span> <span class="nv">$MailFrom</span> <span class="n">-Subject</span> <span class="s2">&quot;MySQL Restarted&quot;</span> <span class="n">-bodyAsHtml</span> <span class="s2">&quot;MySQL host ${MysqlHost} restarted less than 20 minutes ago&quot;</span> <span class="n">-Credential</span> <span class="nb">Get-Credential</span> <span class="n">-SmtpServer</span> <span class="s1">&#39;smtp.office365.com&#39;</span> <span class="n">-Port</span> <span class="n">587</span> <span class="n">-UseSsl</span> +<span class="p">}</span> +</code></pre></div> + +<p>Este script (e os outros que eu utilizo) estão disponíveis no meu GitHub <a href="https://github.com/sipmann/PowerShellScripts">aqui</a>. Tenha em mente que os scripts localizados no GitHub, são um pouco diferentes do que exibido aqui. Espero que tenha achado útil.</p>Monitorando status de replicação do MySQL com PowerShell2020-10-14T19:00:00-03:002020-10-14T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-10-14:/pt/monitoring-mysql-replication-with-powershell.html<p>Tenho migrado alguns scripts bash que tenho para PowerShell, e chegou a vez de migrar um script de monitoramento de replicação do MySQL. Fica como crédito o script original do <a href="https://handyman.dulare.com/mysql-replication-status-alerts-with-bash-script/">Paweł</a>. É um script bem simples onde eu verifico algumas tags resultantes do <code>SHOW SLAVE STATUS\G</code>, são elas. <code>Slave_IO_Running …</code></p><p>Tenho migrado alguns scripts bash que tenho para PowerShell, e chegou a vez de migrar um script de monitoramento de replicação do MySQL. Fica como crédito o script original do <a href="https://handyman.dulare.com/mysql-replication-status-alerts-with-bash-script/">Paweł</a>. É um script bem simples onde eu verifico algumas tags resultantes do <code>SHOW SLAVE STATUS\G</code>, são elas. <code>Slave_IO_Running</code>, <code>Slave_SQL_Running</code> e <code>Seconds_Behind_Master</code>. Ainda preciso verificar formas mais corretas de armazenar/carregar as variáveis como usuários e senha, se tiver alguma dica, fique à vontade para inclusive fazer um pull request (<a href="https://github.com/sipmann/PowerShellScripts">aqui</a>) no repositório onde vou armazenar alguns dos meus scripts.</p> +<div class="highlight"><pre><span></span><code><span class="cm">&lt;#</span> +<span class="cm"> Variables definition</span> +<span class="cm">#&gt;</span> +<span class="nv">$MaxSeconds</span> <span class="p">=</span> <span class="n">120</span> <span class="c"># Max seconds behind master allowed</span> +<span class="nv">$MysqlUser</span> <span class="p">=</span> <span class="s1">&#39;root&#39;</span> +<span class="nv">$MysqlPass</span> <span class="p">=</span> <span class="s1">&#39;&#39;</span> + +<span class="nv">$MailTo</span> <span class="p">=</span> <span class="s1">&#39;mauricio@sipmann.com&#39;</span> +<span class="nv">$MailFrom</span> <span class="p">=</span> <span class="s1">&#39;mauricio@sipmann.com&#39;</span> + + +<span class="nv">$data</span> <span class="p">=</span> <span class="p">$(</span><span class="n">mysql</span> <span class="n">-u</span> <span class="nv">$MysqlUser</span> <span class="n">-p</span><span class="s2">&quot;$MysqlPass&quot;</span> <span class="n">-e</span> <span class="s1">&#39;SHOW SLAVE STATUS \G&#39;</span><span class="p">)</span> + +<span class="c">#Debug data</span> +<span class="c">#$data = Get-Content &#39;c:\temp\sampleresult.txt&#39;</span> + +<span class="cm">&lt;# Parse the data #&gt;</span> +<span class="nv">$IORunning</span> <span class="p">=</span> <span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Slave_IO_Running:&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> +<span class="nv">$SQLRunning</span> <span class="p">=</span> <span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Slave_SQL_Running:&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> +<span class="nv">$LastErrNo</span> <span class="p">=</span> <span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Last_Errno&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> +<span class="nv">$SecondsBh</span> <span class="p">=</span> <span class="no">[int]</span><span class="p">((</span><span class="nv">$data</span> <span class="p">|</span> <span class="nb">Where-Object</span> <span class="p">{</span> <span class="nv">$_</span> <span class="o">-match</span> <span class="s1">&#39;Seconds_Behind_Master&#39;</span> <span class="p">})</span> <span class="n">-split</span> <span class="s1">&#39;\s+&#39;</span><span class="p">)[</span><span class="n">2</span><span class="p">]</span> + +<span class="k">If</span> <span class="p">(</span><span class="nv">$IORunning</span> <span class="o">-Eq</span> <span class="s1">&#39;No&#39;</span> <span class="o">-Or</span> <span class="nv">$SQLRunning</span> <span class="o">-Eq</span> <span class="s1">&#39;No&#39;</span> <span class="o">-Or</span> <span class="nv">$SecondsBh</span> <span class="o">-gt</span> <span class="nv">$MaxSeconds</span><span class="p">)</span> <span class="p">{</span> + <span class="nv">$MailBody</span> <span class="p">=</span> <span class="s1">&#39;&lt;h1&gt;Problema na replicação&lt;/h1&gt;&lt;br&gt;&#39;</span> + + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39; IO Running: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$IORunning</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39; SQL Running: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$SQLRunning</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39;Seconds Behind: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$SecondsBh</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + <span class="nv">$MailBody</span> <span class="p">+=</span> <span class="s1">&#39; Last Err No: &#39;</span> <span class="p">+</span> <span class="p">(</span><span class="nv">$LastErrNo</span><span class="p">)</span> <span class="p">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span> + + <span class="cm">&lt;# Send e-mail, maybe some telegram message here too #&gt;</span> + <span class="nb">Send-MailMessage</span> <span class="n">-To</span> <span class="nv">$MailTo</span> <span class="n">-From</span> <span class="nv">$MailFrom</span> <span class="n">-Subject</span> <span class="s1">&#39;Problemas na replicação&#39;</span> <span class="n">-bodyAsHtml</span> <span class="nv">$MailBody</span> <span class="n">-Credential</span> <span class="p">(</span><span class="nb">Get-Credential</span><span class="p">)</span> <span class="n">-SmtpServer</span> <span class="s1">&#39;smtp.office365.com&#39;</span> <span class="n">-Port</span> <span class="n">587</span> <span class="n">-UseSsl</span> +<span class="p">}</span> <span class="k">Else</span> <span class="p">{</span> + <span class="nb">Write-Host</span> <span class="s2">&quot;Up and running&quot;</span> +<span class="p">}</span> +</code></pre></div>O poder do PowerShell2020-09-21T19:00:00-03:002020-09-21T19:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-09-21:/pt/the-power-of-powershell.html<p>Como um usuário linux por muito tempo, eu automatizei algumas tarefas com scripts bash e fiquei longe do PowerShell... Voltei a utilizar Windows alguns anos atrás e ainda assim, não dei uma chance ao PS. Mas porque não? Eu fiz alguns scripts para automatizar algumas tarefas em um servidor Protheus …</p><p>Como um usuário linux por muito tempo, eu automatizei algumas tarefas com scripts bash e fiquei longe do PowerShell... Voltei a utilizar Windows alguns anos atrás e ainda assim, não dei uma chance ao PS. Mas porque não? Eu fiz alguns scripts para automatizar algumas tarefas em um servidor Protheus.</p> +<p>Eu acabei achando os scripts PS de fácil leitura e entendimento. Abaixo, nós temos um script para remover arquivos filtrando pela sua extensão (ou sem extensão alguma no caso do script em questão).</p> +<div class="highlight"><pre><span></span><code><span class="nb">Get-ChildItem</span> <span class="s2">&quot;C:\TOTVS\protheus_data\system&quot;</span> <span class="o">-File</span> <span class="n">-Filter</span> <span class="p">*.</span> <span class="p">|</span> <span class="nb">Move-Item</span> <span class="n">-Force</span> <span class="n">-Destination</span> <span class="p">{</span> + <span class="cm">&lt;# Diretório ao qual os arquivos vão ser movidos. Você pode utilizar formatos de data para nomear os diretórios #&gt;</span> + <span class="cm">&lt;# LastWriteTime é a propriedade do arquivo corrent #&gt;</span> + <span class="nv">$dir</span> <span class="p">=</span> <span class="s2">&quot;C:\bad_files\{0:yyyy\\MM\\dd}&quot;</span> <span class="o">-f</span> <span class="nv">$_</span><span class="p">.</span><span class="n">LastWriteTime</span> + <span class="nv">$null</span> <span class="p">=</span> <span class="n">mkdir</span> <span class="nv">$dir</span> <span class="n">-Force</span> + <span class="s2">&quot;$dir\</span><span class="p">$(</span><span class="nv">$_</span><span class="p">.</span><span class="n">Name</span><span class="p">)</span><span class="s2">&quot;</span> +<span class="p">}</span> +</code></pre></div> + +<p>Você já precisou remover arquivos baseado no conteúdo de outro arquivo? Abaixo um script onde eu leio um arquivo que contem os nomes de arquivos que eu desejo remover. </p> +<div class="highlight"><pre><span></span><code><span class="k">foreach</span><span class="p">(</span><span class="nv">$line</span> <span class="k">in</span> <span class="nb">Get-Content</span> <span class="p">.\</span><span class="n">Desktop</span><span class="p">\</span><span class="n">bad_files</span><span class="p">.</span><span class="n">txt</span><span class="p">)</span> <span class="p">{</span> + <span class="k">if</span> <span class="p">(</span><span class="nb">Test-Path</span><span class="p">(</span><span class="s1">&#39;\\x.y.z.a\c$\TOTVS\protheus_data\xmls\&#39;</span><span class="p">+</span><span class="nv">$line</span><span class="p">+</span><span class="s1">&#39;.xml&#39;</span><span class="p">))</span> <span class="p">{</span> + <span class="nb">Remove-Item</span><span class="p">(</span><span class="s1">&#39;\\x.y.z.a\c$\TOTVS\protheus_data\xmls\&#39;</span><span class="p">+</span><span class="nv">$line</span><span class="p">+</span><span class="s1">&#39;.xml&#39;</span><span class="p">)</span> + <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> + <span class="nb">echo </span><span class="nv">$line</span> <span class="p">+</span> <span class="s1">&#39; - File not found&#39;</span> + <span class="p">}</span> +<span class="p">}</span> +</code></pre></div> + +<p>E um script bonus para parar e iniciar serviços (se você gerencia um servidor Protheus, você sabe o porque eu faço isto).</p> +<div class="highlight"><pre><span></span><code><span class="nv">$servicesNames</span> <span class="p">=</span> <span class="s1">&#39;app_main&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker1&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker2&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker3&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker4&#39;</span><span class="p">,</span> + <span class="s1">&#39;app_worker5&#39;</span> + +<span class="nb">Write-host</span> <span class="s2">&quot;Parando Serviços&quot;</span> +<span class="nb">Write-host</span> <span class="s2">&quot;--------------------------&quot;</span> + +<span class="k">foreach</span> <span class="p">(</span><span class="nv">$srv</span> <span class="k">in</span> <span class="nv">$servicesNames</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Write-host</span> <span class="s2">&quot;Parando: &quot;</span> <span class="p">+</span> <span class="nv">$srv</span> + <span class="nv">$SrvPID</span> <span class="p">=</span> <span class="p">(</span><span class="nb">get-wmiobject</span> <span class="n">win32_service</span> <span class="p">|</span> <span class="nb">where </span><span class="p">{</span> <span class="nv">$_</span><span class="p">.</span><span class="n">name</span> <span class="o">-eq</span> <span class="nv">$srv</span><span class="p">}).</span><span class="n">processID</span> + <span class="nb">Write-host</span> <span class="s2">&quot;PID: &quot;</span> <span class="p">+</span> <span class="nv">$SrvPID</span> + + <span class="cm">&lt;# Força a parada caso o serviço esteja travado #&gt;</span> + <span class="nb">Stop-Process</span> <span class="nv">$ServicePID</span> <span class="n">-Force</span> + <span class="nb">Write-host</span> <span class="s2">&quot;PDI &quot;</span> <span class="p">+</span> <span class="nv">$SrvPID</span> <span class="p">+</span> <span class="s2">&quot; parado&quot;</span> +<span class="p">}</span> + + +<span class="nb">Write-host</span> <span class="s2">&quot;Inicializando Serviços&quot;</span> +<span class="nb">Write-host</span> <span class="s2">&quot;--------------------------&quot;</span> + +<span class="k">foreach</span> <span class="p">(</span><span class="nv">$srv</span> <span class="k">in</span> <span class="nv">$servicesNames</span><span class="p">)</span> <span class="p">{</span> + <span class="nb">Write-host</span> <span class="s2">&quot;Inicializando: &quot;</span> <span class="p">+</span> <span class="nv">$srv</span> + <span class="nb">Start-Service</span> <span class="nv">$srv</span> +<span class="p">}</span> +</code></pre></div> + +<p>Você tem algum script de automação? Compartilhe conosco :)</p> \ No newline at end of file diff --git a/pt/feeds/powershell.atom.xml.gz b/pt/feeds/powershell.atom.xml.gz new file mode 100644 index 000000000..e73d1dd4f Binary files /dev/null and b/pt/feeds/powershell.atom.xml.gz differ diff --git a/pt/feeds/python.atom.xml b/pt/feeds/python.atom.xml new file mode 100644 index 000000000..ee453ba29 --- /dev/null +++ b/pt/feeds/python.atom.xml @@ -0,0 +1,238 @@ + +Sipmann - Pythonhttps://www.sipmann.com/pt/2018-01-21T21:17:00-02:00Menu dinâmico com as apps do django2018-01-21T21:17:00-02:002018-01-21T21:17:00-02:00Maurício Camargo Sipmanntag:www.sipmann.com,2018-01-21:/pt/menu-dinamico-com-apps-do-django.html<p>Digamos que sua empresa trabalha com Django desenvolvendo aplicações cujas apps são plugaveis e reutilizáveis. Por que não se aproveitar de um certo padrão de desenvolvimento para desenvolver menus que se modificam de acordo com as apps que estão no projeto? Como o objetivo aqui não é desenvolver uma app …</p><p>Digamos que sua empresa trabalha com Django desenvolvendo aplicações cujas apps são plugaveis e reutilizáveis. Por que não se aproveitar de um certo padrão de desenvolvimento para desenvolver menus que se modificam de acordo com as apps que estão no projeto? Como o objetivo aqui não é desenvolver uma app em si, vamos utilizar um projeto com algumas de modelo. Se desejar estudar mais sobre desenvolvimento Django, a documentação é muito boa, mas também temos blogs e sites excelentes sobre o assunto.</p> +<p>Para conseguirmos atingir esse objetivo, vamos utilizar a api <a class="reference external" href="https://docs.djangoproject.com/en/2.0/ref/settings/#installed-apps">Django.apps</a> que está disponível a partir da versão 1.7. +Com esta api, vamos percorrer as apps e se possível, criar um link para uma URL base de cada uma delas. Para começo, baixe os fontes do <a class="reference external" href="https://github.com/sipmann/menusapp-django/releases/tag/v1">projeto aqui</a>, rode o pip install do projeto e no fim, sua estrutura de pastas deve ficar como abaixo.</p> +<div class="highlight"><pre><span></span>../menusapp/ +├── comentarios +│ ├── templates +│ │ └── comentarios +│ │ └── listagem.html +│ ├── __init__.py +│ ├── admin.py +│ ├── apps.py +│ ├── models.py +│ ├── tests.py +│ ├── urls.py +│ └── views.py +├── core +│ ├── templates +│ │ └── core +│ │ └── base.html +│ │ └── listagem.html +│ ├── __init__.py +│ ├── admin.py +│ ├── apps.py +│ ├── models.py +│ ├── tests.py +│ ├── urls.py +│ └── views.py +├── menusapp +│ ├── __init__.py +│ ├── settings.py +│ ├── urls.py +│ └── wsgi.py +└── manage.py +</pre></div> +<p>Rode o projeto e veja como é o seu funcionamento. É na app core que temos a base do nosso HTML, então será nele que iremos trabalhar. Quando se trata de algo que será renderizado no template base, eu gosto muito de utilizar 'template tags' para facilitar. +Neste <a class="reference external" href="http://www.sipmann.com/editando-o-admin-do-django.html">link</a> tem mais um exemplo de utilização de 'template tag' caso esteja interessado.</p> +<p>Vamos então criar uma pasta chamada template_tag e dentro dela a nossa tag. Vamos chamá-la de menus_tag.py. Abaixo vamos ver um pouco da nossa tag. +O código é bem simples e auto explicativo, importamos as bibliotecas necessárias e realizamos o &#64;register da tag com o nome do template que será renderizado. +E por ultimo, retornamos uma tupla de dados para o template.</p> +<div class="livros"> + <div class="recomendacoes">Recomendações</div> + <a rel="noopener" href="https://www.amazon.com.br/gp/product/8575225081/ref=as_li_ss_il?ie=UTF8&linkCode=li2&tag=sipmann-20&linkId=c17fa3ac84e734741a3761e874d7d286" target="_blank"><img border="0" src="//ws-na.amazon-adsystem.com/widgets/q?_encoding=UTF8&ASIN=8575225081&Format=_SL160_&ID=AsinImage&MarketPlace=BR&ServiceVersion=20070822&WS=1&tag=sipmann-20" ></a><img src="https://ir-br.amazon-adsystem.com/e/ir?t=sipmann-20&l=li2&o=33&a=8575225081" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /> + <a rel="noopener" href="https://www.amazon.com.br/gp/product/B074ZTLKHB/ref=as_li_ss_il?ie=UTF8&linkCode=li2&tag=sipmann-20&linkId=e2f37c07da2dc4111ae47854b205d01a" target="_blank"><img border="0" src="//ws-na.amazon-adsystem.com/widgets/q?_encoding=UTF8&ASIN=B074ZTLKHB&Format=_SL160_&ID=AsinImage&MarketPlace=BR&ServiceVersion=20070822&WS=1&tag=sipmann-20" ></a><img src="https://ir-br.amazon-adsystem.com/e/ir?t=sipmann-20&l=li2&o=33&a=B074ZTLKHB" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /> +</div><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django</span> <span class="kn">import</span> <span class="n">template</span> +<span class="kn">from</span> <span class="nn">django.apps</span> <span class="kn">import</span> <span class="n">apps</span> + +<span class="c1">#Carrega o registro de template tags</span> +<span class="n">register</span> <span class="o">=</span> <span class="n">template</span><span class="o">.</span><span class="n">Library</span><span class="p">()</span> + +<span class="c1">#Registra o metodo a seguir como uma inclusion_tag indicando o template a ser renderizado</span> +<span class="nd">@register</span><span class="o">.</span><span class="n">inclusion_tag</span><span class="p">(</span><span class="s1">&#39;menus_por_app.html&#39;</span><span class="p">)</span> +<span class="k">def</span> <span class="nf">menus_por_app</span><span class="p">():</span> + <span class="n">lst</span> <span class="o">=</span> <span class="n">apps</span><span class="o">.</span><span class="n">get_app_configs</span><span class="p">()</span> + <span class="k">return</span> <span class="p">{</span> <span class="s1">&#39;lst_apps&#39;</span> <span class="p">:</span> <span class="n">lst</span> <span class="p">}</span> +</pre></div> +<p>O template está abaixo e é simplesmente um for percorrendo as apps e gerando uma lista com os seus menus. As outras propriedades você pode ver direto na <a class="reference external" href="https://docs.djangoproject.com/en/2.0/ref/applications/#django.apps.AppConfig">documentação</a>. +Algumas ressalvas para o que foi feito por questões de praticidade para uso posterior, utilizei um with para concatenar e gerar a url e criei um apelido para a url para validar a existência da mesma. Fora isto, nada de novo.</p> +<div class="highlight"><pre><span></span>{% if not lst_apps %} + <span class="p">&lt;</span><span class="nt">p</span><span class="p">&gt;</span>Nenhuma app<span class="p">&lt;/</span><span class="nt">p</span><span class="p">&gt;</span> + {% else %} + <span class="p">&lt;</span><span class="nt">ul</span><span class="p">&gt;</span> + {% for app in lst_apps %} + {% with app.name|add:&quot;:listagem&quot; as link %} + {% url link as the_url %} + {% if the_url %} + <span class="p">&lt;</span><span class="nt">li</span><span class="p">&gt;</span> + <span class="p">&lt;</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">&quot;{% url link %}&quot;</span><span class="p">&gt;</span>{{ app.verbose_name|truncatechars:30 }}<span class="p">&lt;/</span><span class="nt">a</span><span class="p">&gt;</span> + <span class="p">&lt;/</span><span class="nt">li</span><span class="p">&gt;</span> + {% endif %} + {% endwith %} + {% endfor %} + <span class="p">&lt;/</span><span class="nt">ul</span><span class="p">&gt;</span> + {% endif %} +</pre></div> +<img alt="Resultado final" src="/images/menu_apps.png" /> +<p>No final, o resultado obtido deve ser semelhante ao acima. Repare que está listando as duas aplicações. E acima de tudo, repare que só serão exibidos os links cuja app tenha um namespace de mesmo nome e uma url de nome <cite>listagem</cite>. +A estrutura final pode ser vista abaixo. Atente-se aos nomes tanto das pastas quanto dos arquivos, pois qualquer diferença pode causar o não funcionamento.</p> +<div class="highlight"><pre><span></span>../menusapp/ +├── comentarios +│ ├── templates +│ │ └── comentarios +│ │ └── listagem.html +│ ├── __init__.py +│ ├── admin.py +│ ├── apps.py +│ ├── models.py +│ ├── tests.py +│ ├── urls.py +│ └── views.py +├── core +│ ├── templates +│ │ └── core +│ │ │ └── base.html +│ │ │ └── listagem.html +│ │ └── menus_por_app.html +│ ├── templatetags +│ │ ├── __init__.py +│ │ └── menus_tag.py +│ ├── __init__.py +│ ├── admin.py +│ ├── apps.py +│ ├── models.py +│ ├── tests.py +│ ├── urls.py +│ └── views.py +├── menusapp +│ ├── __init__.py +│ ├── settings.py +│ ├── urls.py +│ └── wsgi.py +└── manage.py +</pre></div> +<p>Espero que tenham gostado, críticas e sugestões são bem-vindas. <a class="reference external" href="https://github.com/sipmann/menusapp-django/releases/tag/v2">Fontes do Projeto</a></p> +Editando o Admin do Django2014-05-15T18:00:00-03:002014-05-15T18:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2014-05-15:/pt/editando-o-admin-do-django.html<p>Este artigo foi re-postado no grupo <a class="reference external" href="http://pythonclub.com.br/editando-o-admin-do-django.html">PythonClub</a>. Vamos falar um pouco sobre como customizar o admin do Django. Primeiramente porque? A resposta é bem simples, quero mostrar algo para o usuário sem que ele precise entrar nas apps e fazer alguma consulta para então tomar alguma ação. Alguns exêmplos para …</p><p>Este artigo foi re-postado no grupo <a class="reference external" href="http://pythonclub.com.br/editando-o-admin-do-django.html">PythonClub</a>. Vamos falar um pouco sobre como customizar o admin do Django. Primeiramente porque? A resposta é bem simples, quero mostrar algo para o usuário sem que ele precise entrar nas apps e fazer alguma consulta para então tomar alguma ação. Alguns exêmplos para isto seriam:</p> +<blockquote> +<ul class="simple"> +<li>Exibir as vendas do mês em forma de gráfico por região do país</li> +<li>Exibir os últimos comentários adicionados</li> +<li>Exibir log dos ultimos usuários cadastrados</li> +</ul> +</blockquote> +<p>O que faremos aqui será exibir os últimos comentários ainda não liberados de um sistema de blog. Vale lembrar que aqui não discutiremos sobre os primeiros passos da aplicação. Para seguirmos adiante, vamos assumir que já temos um projeto básico com uma estrutura simples, abaixo a estrutura inicial do nosso projeto.</p> +<div class="highlight"><pre><span></span>../blog/ +├── core +│ ├── __init__.py +│ ├── admin.py +│ ├── models.py +│ ├── tests.py +│ └── views.py +├── blog +│ ├── __init__.py +│ ├── settings.py +│ ├── urls.py +│ └── wsgi.py +└── manage.py +</pre></div> +<p>Para iniciarmos, precisamos da nossa tabela de comentários, vamos usar a mais simples e básica o possível.</p> +<table border="1" class="docutils"> +<colgroup> +<col width="50%" /> +<col width="50%" /> +</colgroup> +<thead valign="bottom"> +<tr><th class="head">Campo</th> +<th class="head">Tipo</th> +</tr> +</thead> +<tbody valign="top"> +<tr><td>nome</td> +<td>Varchar(30)</td> +</tr> +<tr><td>texto</td> +<td>Text</td> +</tr> +<tr><td>liberado</td> +<td>Boolean</td> +</tr> +<tr><td>data</td> +<td>Date</td> +</tr> +</tbody> +</table> +<p>Vamos seguir adiante e alterar a página inicial do admin para listar os últimos comentários de um simples sistema de blog. Para comerçar a editar o admin, precisamos inicialmente copiar o template que desejamos para a pasta uma pasta <cite>admin</cite> dentro ta pasta de templates do nosso projeto. Isto porque o Admin, não passa de uma app como outra qualquer, portanto o sistema de herança vai funcionar aqui, carregamento prioritariamente o seu template. Você pode conseguir o template que desejar (no nosso caso o index.html) dentro do projeto do Django mesmo, no meu caso &quot;C:\Django-1.6.3\django\contrib\admin\templates\admin&quot;.</p> +<div class="highlight"><pre><span></span>../blog/ +├── templates +│ ├── admin +│ │ └── index.html +├── core +</pre></div> +<p>Tire um tempo e brinque um pouco com este template e veja o que acontece se você alterar algumas coisa. Para adicionarmos a nossa listagem, vamos adicionar um painel lateral, para tal vamos adicionar o código abaixo antes do fechamento da ultima tag div. Nele podemos ver uma chamada para uma template_tag, portanto precisamos carrega-la no topo do template.</p> +<div class="highlight"><pre><span></span>{% load comentarios_tag %} +... +... +... +<span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">&quot;module&quot;</span> <span class="na">id</span><span class="o">=</span><span class="s">&quot;ultimos-comentarios&quot;</span><span class="p">&gt;</span> + <span class="p">&lt;</span><span class="nt">h2</span><span class="p">&gt;</span>Ultimos Comentários<span class="p">&lt;/</span><span class="nt">h2</span><span class="p">&gt;</span> + <span class="p">&lt;</span><span class="nt">h3</span><span class="p">&gt;</span>Liberar<span class="p">&lt;/</span><span class="nt">h3</span><span class="p">&gt;</span> + {% comentarios_n_liberados %} +<span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span> +</pre></div> +<p>Esta template trata-se da responsável por fazer a consulta na base de dados e renderizar a nossa lista, portanto ela é uma 'inclusion tag'. Se você não esta familiarizado com 'template tags', talvez queira dar uma olhada na <a class="reference external" href="https://docs.djangoproject.com/en/dev/howto/custom-template-tags/">documentação do django</a>.</p> +<p>Vamos então criar nossa template tag 'comentarios_n_liberados'. Primeiro devemos criar uma pasta chamada templatetags, dentro da nossa app core. Dentro ta pasta vamos inicializar um pacote python e criar o arquivo comentarios_tag.py. Nele precisamos declarar nosso metodo que deve se chamar 'comentarios_n_liberados' e nele fazer uma simples consulta ao banco buscando os comentários não liberados e por fim registrar a tag apontando para o template que será renderizado. Abaixo o código mais explicado.</p> +<div class="livros"> + <div class="recomendacoes">Recomendações</div> + <a rel="noopener nofollow" href="https://www.amazon.com.br/gp/product/8575225081/ref=as_li_ss_il?ie=UTF8&linkCode=li2&tag=sipmann-20&linkId=c17fa3ac84e734741a3761e874d7d286" target="_blank"><img border="0" src="//ws-na.amazon-adsystem.com/widgets/q?_encoding=UTF8&ASIN=8575225081&Format=_SL160_&ID=AsinImage&MarketPlace=BR&ServiceVersion=20070822&WS=1&tag=sipmann-20" ></a><img src="https://ir-br.amazon-adsystem.com/e/ir?t=sipmann-20&l=li2&o=33&a=8575225081" alt="Livro Pense em Python na Amazon" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /> + <a rel="noopener nofollow" href="https://www.amazon.com.br/gp/product/B074ZTLKHB/ref=as_li_ss_il?ie=UTF8&linkCode=li2&tag=sipmann-20&linkId=e2f37c07da2dc4111ae47854b205d01a" target="_blank"><img border="0" src="//ws-na.amazon-adsystem.com/widgets/q?_encoding=UTF8&ASIN=B074ZTLKHB&Format=_SL160_&ID=AsinImage&MarketPlace=BR&ServiceVersion=20070822&WS=1&tag=sipmann-20" ></a><img src="https://ir-br.amazon-adsystem.com/e/ir?t=sipmann-20&l=li2&o=33&a=B074ZTLKHB" alt="Livro Curso Intensivo de Python na Amazon" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /> +</div><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django</span> <span class="kn">import</span> <span class="n">template</span> +<span class="kn">from</span> <span class="nn">core</span> <span class="kn">import</span> <span class="n">models</span> + +<span class="c1">#Carrega o registro de template tags</span> +<span class="n">register</span> <span class="o">=</span> <span class="n">template</span><span class="o">.</span><span class="n">Library</span><span class="p">()</span> + +<span class="c1">#Registra o metodo a seguir como uma inclusion_tag indicando o template a ser renderizad</span> +<span class="nd">@register</span><span class="o">.</span><span class="n">inclusion_tag</span><span class="p">(</span><span class="s1">&#39;comentarios_n_liberados.html&#39;</span><span class="p">)</span> +<span class="k">def</span> <span class="nf">comentarios_n_liberados</span><span class="p">():</span> + <span class="n">comentarios</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">comentario</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">liberado</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span><span class="o">.</span><span class="n">order_by</span><span class="p">(</span><span class="s1">&#39;data&#39;</span><span class="p">)[</span><span class="mi">0</span><span class="p">:</span><span class="mi">5</span><span class="p">]</span> + <span class="k">return</span> <span class="p">{</span> <span class="s1">&#39;comentarios&#39;</span> <span class="p">:</span> <span class="n">comentarios</span> <span class="p">}</span> +</pre></div> +<p>Abaixo o html do nosso template a ser renderizado, este deve estar dentro da pasta templates da nossa app core.</p> +<div class="highlight"><pre><span></span>{% if not comentarios %} + <span class="p">&lt;</span><span class="nt">p</span><span class="p">&gt;</span>Nenhum comentário novo<span class="p">&lt;/</span><span class="nt">p</span><span class="p">&gt;</span> +{% else %} + <span class="p">&lt;</span><span class="nt">ul</span><span class="p">&gt;</span> + {% for c in comentarios %} + <span class="p">&lt;</span><span class="nt">li</span> <span class="na">class</span><span class="o">=</span><span class="s">&quot;addlink&quot;</span><span class="p">&gt;</span> + <span class="p">&lt;</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">&quot;{{ c.id }}&quot;</span><span class="p">&gt;</span>{{ c.texto|truncatechars:30 }}<span class="p">&lt;/</span><span class="nt">a</span><span class="p">&gt;</span> + <span class="p">&lt;/</span><span class="nt">li</span><span class="p">&gt;</span> + {% endfor %} + <span class="p">&lt;/</span><span class="nt">ul</span><span class="p">&gt;</span> +{% endif %} +</pre></div> +<p>Com tudo isto feito, basta subir o seu servidor e ver o resultado final, que pode ser visto na imagem abaixo.</p> +<img alt="Resultado final" src="images/admin_modificado.png" /> +<p>Lembrando que aqui apenas mostrei como modificar o index do admin, para apenas listar dados do banco, mas você pode ir muito mais além. Abaixo fica a estrutura de diretórios final e um link para download do projeto funcionando.</p> +<div class="highlight"><pre><span></span>../blog/ +├── core +│ ├── templates +│ │ └── comentarios_n_liberados.html +│ ├── templatetag +│ │ └── comentarios_tag.py +│ ├── __init__.py +│ ├── admin.py +│ ├── models.py +│ ├── tests.py +│ └── views.py +├── blog +│ ├── __init__.py +│ ├── settings.py +│ ├── urls.py +│ └── wsgi.py +├── templates +│ ├── admin +│ │ └── index.html +└── manage.py +</pre></div> +<p>Espero que tenham gostado, criticas/sugestões são bem-vindas. <a class="reference external" href="https://github.com/sipmann/editando-django-admin">Fontes do Projeto</a></p> + \ No newline at end of file diff --git a/pt/feeds/python.atom.xml.gz b/pt/feeds/python.atom.xml.gz new file mode 100644 index 000000000..e3259fe57 Binary files /dev/null and b/pt/feeds/python.atom.xml.gz differ diff --git a/pt/feeds/shell.atom.xml b/pt/feeds/shell.atom.xml new file mode 100644 index 000000000..4b672936a --- /dev/null +++ b/pt/feeds/shell.atom.xml @@ -0,0 +1,41 @@ + +Sipmann - Shellhttps://www.sipmann.com/pt/2017-10-08T18:00:00-03:00Scripts de inicialização no raspberry pi2017-10-08T18:00:00-03:002017-10-08T18:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2017-10-08:/pt/script-de-inicializacao-raspberry.html<p>Instalei essa semana o <a class="reference external" href="https://gitea.io">gitea</a> no meu raspberry pi B + e queria iniciar ele no boot... Não sou profundo conhecedor de linux, então, logo não sabia como fazer isto da melhor forma. +As versões atuais do Raspbian utilizam o <cite>systemd</cite> para gerenciar os serviços e confesso que nunca havia utilizado …</p><p>Instalei essa semana o <a class="reference external" href="https://gitea.io">gitea</a> no meu raspberry pi B + e queria iniciar ele no boot... Não sou profundo conhecedor de linux, então, logo não sabia como fazer isto da melhor forma. +As versões atuais do Raspbian utilizam o <cite>systemd</cite> para gerenciar os serviços e confesso que nunca havia utilizado o systemctl para nada.</p> +<p>Vamos começa criando um arquivo de serviço dentro da pasta <cite>/etc/systemd/system</cite>, vale ressaltar que a pasta <cite>system</cite> deve (em teoria) ser reservada para pacotes do sistema. +Vamos criar o arquivo com o nome <cite>gitea.service</cite> dentro da pasta antes mencionada. Abaixo podemos ver como ficou o arquivo e um detalhamento após ele.</p> +<div class="highlight"><pre><span></span><span class="o">[</span>Unit<span class="o">]</span> +<span class="nv">Description</span><span class="o">=</span>Gitea Service +<span class="nv">After</span><span class="o">=</span>network.target + +<span class="o">[</span>Service<span class="o">]</span> +<span class="nv">Type</span><span class="o">=</span>simple +<span class="nv">User</span><span class="o">=</span>root +<span class="nv">WorkingDirectory</span><span class="o">=</span>/root/ +<span class="nv">ExecStart</span><span class="o">=</span>/root/gitea web +<span class="nv">Restart</span><span class="o">=</span>on-abort +</pre></div> +<p>A composição do arquivo é bem simples, mas vamos a alguns detalhes. <cite>Type</cite> possui várias opções (simple, forking, oneshot), utilizamos <cite>simple</cite> uma vez que o nosso processo executara, permanecerá rodando e não executa um fork de processo. +Fork como acabo de comentar, deve ser utilizado caso o processo que for executando disparar mais processos. User irá definir o usuário do processo. <cite>WorkingDirectory</cite> definira onde o processo terá a sua base de execução, como o gitea esta localizada na pasta root, +aponto para lá. O ExecStart é bem simples e direto, deve chamar a execução do processo passando parametros caso seja necessário. O <cite>Restart</cite> é o que nos garantirá que o serviço permanecerá rodando caso haja algum imprevisto (exceto o fato de um usuário chamar o stop).</p> +<p>Salve o arquivo e vamos rodar um refresh para o SO perceber o novo serviço. Assim rodamos <cite>systemctl daemon-reload</cite>. Sempre que alterarmos um serviço ou criarmos um novo, este comando deve ser executado, caso contrário o próprio systemctl pode lhe alertar da necessidade. +Após reacarregar os serviços, vamos habilitar o serviço que criamos rodando <cite>systemctl enable gitea</cite>, feito isto temos alguns comandos uteis.</p> +<ul class="simple"> +<li>systemctl start gitea</li> +<li>systemctl stop gitea</li> +<li>systemctl status gitea</li> +</ul> +<p>O comando de status pode ser visto como exemplo abaixo.</p> +<div class="highlight"><pre><span></span>● gitea.service - Gitea Service + Loaded: loaded <span class="o">(</span>/etc/systemd/system/gitea.service<span class="p">;</span> enabled<span class="p">;</span> vendor preset: enabled<span class="o">)</span> + Active: active <span class="o">(</span>running<span class="o">)</span> since Wed <span class="m">2017</span>-10-04 <span class="m">00</span>:37:34 UTC<span class="p">;</span> 52min ago +Main PID: <span class="m">1087</span> <span class="o">(</span>gitea<span class="o">)</span> + CGroup: /system.slice/gitea.service + └─1087 /root/gitea web + +Oct <span class="m">04</span> <span class="m">00</span>:38:31 gitserver gitea<span class="o">[</span><span class="m">1087</span><span class="o">]</span>: <span class="o">[</span>Macaron<span class="o">]</span> <span class="m">2017</span>-10-04 <span class="m">00</span>:38:31: Completed /explore/users <span class="m">200</span> OK in <span class="m">80</span>.106173ms +Oct <span class="m">04</span> <span class="m">00</span>:38:31 gitserver gitea<span class="o">[</span><span class="m">1087</span><span class="o">]</span>: <span class="o">[</span>Macaron<span class="o">]</span> <span class="m">2017</span>-10-04 <span class="m">00</span>:38:31: Started GET /img/favicon.png <span class="k">for</span> <span class="m">192</span>.168.1.4 +Oct <span class="m">04</span> <span class="m">00</span>:38:31 gitserver gitea<span class="o">[</span><span class="m">1087</span><span class="o">]</span>: <span class="o">[</span>Macaron<span class="o">]</span> <span class="o">[</span>Static<span class="o">]</span> Serving /img/favicon.png +</pre></div> +<p>Após estes processos, você pode reiniciar seu raspberry que o gitea irá subir e funcionar. Ressalto que, preste atenção tanto no <cite>WorkingDirectory</cite> quanto no <cite>ExecStart</cite>, no caso do gitea, ele utiliza o workingdir e a forma de start para saber onde irá largar os arquivos por padrão, então ou você configura ele com caminhos absolutos ou cuidar na forma de start (ao menos é o que consegui pegar até agora).</p> + \ No newline at end of file diff --git a/pt/feeds/shell.atom.xml.gz b/pt/feeds/shell.atom.xml.gz new file mode 100644 index 000000000..ce5840bc1 Binary files /dev/null and b/pt/feeds/shell.atom.xml.gz differ diff --git a/pt/feeds/sql-server.atom.xml b/pt/feeds/sql-server.atom.xml new file mode 100644 index 000000000..038f6adfc --- /dev/null +++ b/pt/feeds/sql-server.atom.xml @@ -0,0 +1,118 @@ + +Sipmann - SQL Serverhttps://www.sipmann.com/pt/2020-11-14T07:00:00-03:00Bloqueando um usuário do SQL Server baseado em uma tabela de horários2020-11-14T07:00:00-03:002020-11-14T07:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-11-14:/pt/blocking-user-on-sql-server-based-on-schedule.html<p>Ok, algum tempo atrás, eu postei sobre como você pode impor limites às conexões do SQL Server utilizando o <a href="https://www.sipmann.com/limiting-connection-resources-sql-server.html#.X6Cz8IhKhPY">Resource Governor</a>. Mas, e se você não pode utilizar ele? Você sempre pode bloquear logins usando uma trigger, mas eu não gosto da ideia de ter um select rodando a cada …</p><p>Ok, algum tempo atrás, eu postei sobre como você pode impor limites às conexões do SQL Server utilizando o <a href="https://www.sipmann.com/limiting-connection-resources-sql-server.html#.X6Cz8IhKhPY">Resource Governor</a>. Mas, e se você não pode utilizar ele? Você sempre pode bloquear logins usando uma trigger, mas eu não gosto da ideia de ter um select rodando a cada login. Então, eu cheguei a esta solução, utilizando uma stored procedure, uma tabela e o Agent.</p> +<p>A ideia principal é armazenar o horário em que um usuário deve ser bloqueado pelo Agent. Abaixo você pode ver a criação da tabela:</p> +<div class="highlight"><pre><span></span><code><span class="k">CREATE</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"> </span><span class="p">(</span><span class="w"></span> +<span class="w"> </span><span class="n">Id</span><span class="w"> </span><span class="nc">INT</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">LoginName</span><span class="w"> </span><span class="nc">NVARCHAR</span><span class="p">(</span><span class="mi">100</span><span class="p">)</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"></span> +<span class="w"> </span><span class="n">HrInicio</span><span class="w"> </span><span class="nc">TIME</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"> </span><span class="cm">/* horário de inicio do bloqueio */</span><span class="w"></span> +<span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="nc">TIME</span><span class="w"> </span><span class="ow">NOT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w"> </span><span class="cm">/*horário de termino */</span><span class="w"></span> +<span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="nc">INT</span><span class="w"> </span><span class="k">DEFAULT</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="cm">/* 0 = desbloqueado, 1 = bloqueado */</span><span class="w"></span> +<span class="w"> </span><span class="k">PRIMARY</span><span class="w"> </span><span class="k">KEY</span><span class="w"> </span><span class="p">(</span><span class="n">Id</span><span class="p">)</span><span class="w"></span> +<span class="p">);</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> + +<span class="cm">/* regra para Não bloquear o usuário SA */</span><span class="w"></span> +<span class="k">ALTER</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"></span> +<span class="w"> </span><span class="k">ADD</span><span class="w"> </span><span class="k">CONSTRAINT</span><span class="w"> </span><span class="n">chk_users</span><span class="w"> </span><span class="k">CHECK</span><span class="w"> </span><span class="p">(</span><span class="n">LoginName</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;sa&#39;</span><span class="p">));</span><span class="w"></span> + +<span class="k">ALTER</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"></span> +<span class="w"> </span><span class="k">ADD</span><span class="w"> </span><span class="k">CONSTRAINT</span><span class="w"> </span><span class="n">chk_hora_final_maior</span><span class="w"> </span><span class="k">CHECK</span><span class="w"> </span><span class="p">(</span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="n">HrInicio</span><span class="p">);</span><span class="w"></span> + +<span class="k">ALTER</span><span class="w"> </span><span class="nc">TABLE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">HorariosBloqueio</span><span class="w"></span> +<span class="w"> </span><span class="k">ADD</span><span class="w"> </span><span class="k">CONSTRAINT</span><span class="w"> </span><span class="n">chk_status_bloqueio</span><span class="w"> </span><span class="k">CHECK</span><span class="w"> </span><span class="p">(</span><span class="n">Bloqueado</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">));</span><span class="w"></span> + +<span class="k">CREATE</span><span class="w"> </span><span class="k">SEQUENCE</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">seq_HorariosBloqueio</span><span class="w"> </span><span class="k">START</span><span class="w"> </span><span class="k">WITH</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="n">INCREMENT</span><span class="w"> </span><span class="k">BY</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +</code></pre></div> + +<p>Depois de criar a tabela, vamos verificar a procedure que vai fazer todo o trabalho de habilitar/desabilitar os usuários. Fique ciente que, nesta procedure, eu defini o nome do banco onde a tabela está armazenada. Você pode substituir o nome <code>DBATOOLS</code> pelo o nome da sua base.</p> +<div class="highlight"><pre><span></span><code><span class="k">IF</span><span class="w"> </span><span class="nf">OBJECT_ID</span><span class="p">(</span><span class="s1">&#39;dbo.sp_ValidarLogin&#39;</span><span class="p">)</span><span class="w"> </span><span class="k">IS</span><span class="w"> </span><span class="k">NULL</span><span class="w"></span> +<span class="w"> </span><span class="k">EXEC</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;CREATE PROCEDURE dbo.sp_ValidarLogin AS RETURN 0;&#39;</span><span class="p">);</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> + +<span class="k">CREATE</span><span class="w"> </span><span class="ow">OR</span><span class="w"> </span><span class="k">ALTER</span><span class="w"> </span><span class="k">PROC</span><span class="w"> </span><span class="n">dbo</span><span class="p">.</span><span class="n">sp_ValidarLogin</span><span class="w"></span> +<span class="k">AS</span><span class="w"> </span><span class="k">BEGIN</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="nc">NVARCHAR</span><span class="p">(</span><span class="mi">100</span><span class="p">);</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="nc">TIME</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="k">SET</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nf">CAST</span><span class="p">(</span><span class="nf">GETDATE</span><span class="p">()</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="nc">TIME</span><span class="p">);</span><span class="w"></span> + +<span class="w"> </span><span class="cm">/* Bloqueia os que ainda não estiverem bloqueados de acordo com a hora atual */</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="n">block_cursor</span><span class="w"> </span><span class="nc">CURSOR</span><span class="w"></span> +<span class="w"> </span><span class="k">FOR</span><span class="w"> </span><span class="k">SELECT</span><span class="w"> </span><span class="n">LoginName</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&lt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&gt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"></span> +<span class="w"> </span><span class="k">OPEN</span><span class="w"> </span><span class="n">block_cursor</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">block_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> + +<span class="w"> </span><span class="k">WHILE</span><span class="w"> </span><span class="nb">@@FETCH_STATUS</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"></span> +<span class="w"> </span><span class="k">BEGIN</span><span class="w"></span> +<span class="w"> </span><span class="k">exec</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;ALTER LOGIN &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="s1">&#39; DISABLE;&#39;</span><span class="p">);</span><span class="w"></span> + +<span class="w"> </span><span class="k">print</span><span class="w"> </span><span class="s1">&#39;Bloqued usuario &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">block_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> +<span class="w"> </span><span class="k">END</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">CLOSE</span><span class="w"> </span><span class="n">block_cursor</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="k">DEALLOCATE</span><span class="w"> </span><span class="n">block_cursor</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">UPDATE</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">SET</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&lt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&gt;=</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"></span> + + +<span class="w"> </span><span class="cm">/* Libera quem estava bloqueado */</span><span class="w"></span> +<span class="w"> </span><span class="k">DECLARE</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="nc">CURSOR</span><span class="w"></span> +<span class="w"> </span><span class="k">FOR</span><span class="w"> </span><span class="k">SELECT</span><span class="w"> </span><span class="n">LoginName</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="p">(</span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">OR</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="p">)</span><span class="w"></span> +<span class="w"> </span><span class="k">OPEN</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> + +<span class="w"> </span><span class="k">WHILE</span><span class="w"> </span><span class="nb">@@FETCH_STATUS</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"></span> +<span class="w"> </span><span class="k">BEGIN</span><span class="w"></span> +<span class="w"> </span><span class="k">exec</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;ALTER LOGIN &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"> </span><span class="o">+</span><span class="s1">&#39; ENABLE;&#39;</span><span class="p">);</span><span class="w"></span> + +<span class="w"> </span><span class="k">print</span><span class="w"> </span><span class="s1">&#39;Unbloqued usuario &#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">@LoginName</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">FETCH</span><span class="w"> </span><span class="k">NEXT</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="nv">@LoginName</span><span class="w"></span> +<span class="w"> </span><span class="k">END</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">CLOSE</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="p">;</span><span class="w"></span> +<span class="w"> </span><span class="k">DEALLOCATE</span><span class="w"> </span><span class="n">unblock_cursor</span><span class="p">;</span><span class="w"></span> + +<span class="w"> </span><span class="k">UPDATE</span><span class="w"> </span><span class="o">[</span><span class="n">DBATOOLS</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="p">.</span><span class="o">[</span><span class="n">HorariosBloqueio</span><span class="o">]</span><span class="w"> </span><span class="k">SET</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">Bloqueado</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="ow">AND</span><span class="w"> </span><span class="p">(</span><span class="n">HrInicio</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="w"> </span><span class="ow">OR</span><span class="w"> </span><span class="n">HrTermino</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="nv">@Momento</span><span class="p">)</span><span class="w"></span> +<span class="k">END</span><span class="p">;</span><span class="w"></span> +</code></pre></div> + +<p>Certo, então agora tudo que temos que fazer é definir o job no Agent para rodar a procedure de minuto em minuto. Novamente, a ideia principal é chamar a procedure quando um usuário deve ser bloqueado e quando deve ser desbloqueado.</p> +<div class="highlight"><pre><span></span><code><span class="err"> -- Vai bloquear o usuário protheus das 10 AM até 15 PM</span> +<span class="err"> INSERT INTO dbo.HorariosBloqueio (Id, LoginName, HrInicio, HrTermino) VALUES (NEXT VALUE FOR seq_HorariosBloqueio, &#39;protheus&#39;, &#39;10:00:00&#39;, &#39;15:00:00&#39;);</span> +</code></pre></div>Removendo um usuário de uma base SQL Server2019-09-06T07:00:00-03:002020-10-21T18:40:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2019-09-06:/pt/removing-user-from-sql-server-database.html<p>O seu cliente lhe pede com urgência para <em>dropar</em> um usuário da sua base MsSQL Server, mas você trava com o seguinte aviso de erro:</p> +<div class="highlight"><pre><span></span><code><span class="n">Error</span><span class="o">:</span> <span class="mi">15138</span> <span class="n">The</span> <span class="n">database</span> <span class="n">principal</span> <span class="n">owns</span> <span class="n">a</span> <span class="n">schema</span> <span class="k">in</span> <span class="n">the</span> <span class="n">database</span><span class="o">,</span> <span class="n">and</span> <span class="n">cannot</span> <span class="n">be</span> <span class="n">dropped</span><span class="o">.</span> +</code></pre></div> + +<p>Se você não possui (ou no momento não consegue acesso …</p><p>O seu cliente lhe pede com urgência para <em>dropar</em> um usuário da sua base MsSQL Server, mas você trava com o seguinte aviso de erro:</p> +<div class="highlight"><pre><span></span><code><span class="n">Error</span><span class="o">:</span> <span class="mi">15138</span> <span class="n">The</span> <span class="n">database</span> <span class="n">principal</span> <span class="n">owns</span> <span class="n">a</span> <span class="n">schema</span> <span class="k">in</span> <span class="n">the</span> <span class="n">database</span><span class="o">,</span> <span class="n">and</span> <span class="n">cannot</span> <span class="n">be</span> <span class="n">dropped</span><span class="o">.</span> +</code></pre></div> + +<p>Se você não possui (ou no momento não consegue acesso) ao SSMS (SQL Server Management Studio) para verificar quais schemas ou objetos o usuário é "dono", a seguinte SQL vai resolver o problema.</p> +<div class="highlight"><pre><span></span><code><span class="k">USE</span><span class="w"> </span><span class="o">[</span><span class="n">DATABASENAME</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> + +<span class="k">select</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Objeto</span><span class="p">,</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Owner</span><span class="w"></span> +<span class="k">from</span><span class="w"> </span><span class="n">sys</span><span class="p">.</span><span class="n">schemas</span><span class="w"> </span><span class="n">so</span><span class="w"></span> +<span class="k">inner</span><span class="w"> </span><span class="k">join</span><span class="w"> </span><span class="n">sysusers</span><span class="w"> </span><span class="n">su</span><span class="w"> </span><span class="k">on</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">principal_id</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">uid</span><span class="w"></span> +<span class="k">where</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">&#39;username&#39;</span><span class="w"></span> + +<span class="k">select</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Objeto</span><span class="p">,</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="n">Owner</span><span class="p">,</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">xtype</span><span class="w"> </span><span class="n">Tipo</span><span class="w"></span> +<span class="k">from</span><span class="w"> </span><span class="n">sys</span><span class="p">.</span><span class="n">sysobjects</span><span class="w"> </span><span class="n">so</span><span class="w"></span> +<span class="k">inner</span><span class="w"> </span><span class="k">join</span><span class="w"> </span><span class="n">sysusers</span><span class="w"> </span><span class="n">su</span><span class="w"> </span><span class="k">on</span><span class="w"> </span><span class="n">so</span><span class="p">.</span><span class="n">uid</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">uid</span><span class="w"></span> +<span class="k">where</span><span class="w"> </span><span class="n">su</span><span class="p">.</span><span class="n">name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">&#39;username&#39;</span><span class="w"></span> +</code></pre></div> + +<p>Assim que você tiver os objetos/schemas que o usuário é dono, você pode alterar os mesmos com a seguinte SQL (exemplo de troca de schema):</p> +<div class="highlight"><pre><span></span><code><span class="k">USE</span><span class="w"> </span><span class="o">[</span><span class="n">DATABASENAME</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +<span class="k">ALTER</span><span class="w"> </span><span class="k">AUTHORIZATION</span><span class="w"> </span><span class="k">ON</span><span class="w"> </span><span class="k">SCHEMA</span><span class="o">::[</span><span class="n">db_datareader</span><span class="o">]</span><span class="w"> </span><span class="k">TO</span><span class="w"> </span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="w"> </span><span class="c1">-- username do novo dono</span> +<span class="k">ALTER</span><span class="w"> </span><span class="k">AUTHORIZATION</span><span class="w"> </span><span class="k">ON</span><span class="w"> </span><span class="k">SCHEMA</span><span class="o">::[</span><span class="n">db_datawriter</span><span class="o">]</span><span class="w"> </span><span class="k">TO</span><span class="w"> </span><span class="o">[</span><span class="n">dbo</span><span class="o">]</span><span class="w"></span> +<span class="k">GO</span><span class="w"></span> +</code></pre></div> + +<p>Então, você pode dropar o usuário <code>DROP USER [username]</code>.</p> \ No newline at end of file diff --git a/pt/feeds/sql-server.atom.xml.gz b/pt/feeds/sql-server.atom.xml.gz new file mode 100644 index 000000000..5b8fb5873 Binary files /dev/null and b/pt/feeds/sql-server.atom.xml.gz differ diff --git a/pt/feeds/tools.atom.xml b/pt/feeds/tools.atom.xml new file mode 100644 index 000000000..73f719c01 --- /dev/null +++ b/pt/feeds/tools.atom.xml @@ -0,0 +1,59 @@ + +Sipmann - Toolshttps://www.sipmann.com/pt/2020-12-02T14:00:00-03:00Apache Nifi JSON to SQL removendo underline2020-12-02T14:00:00-03:002020-12-02T14:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2020-12-02:/pt/apache-nifi-json-to-sql-replacing-underscore.html<p>Recentemente eu estava desenvolvendo alguns processos de ETL com o Apache NiFi. Mas após alguns minutos desenhando o meu fluxo, eu vi um comportamento estranho do componente ConvertJSONToSQL, que estava substituindo os underline ('_') do nome de um campo utilizado na condição da SQL (eu estava preparando um UPDATE). Aquilo …</p><p>Recentemente eu estava desenvolvendo alguns processos de ETL com o Apache NiFi. Mas após alguns minutos desenhando o meu fluxo, eu vi um comportamento estranho do componente ConvertJSONToSQL, que estava substituindo os underline ('_') do nome de um campo utilizado na condição da SQL (eu estava preparando um UPDATE). Aquilo estava estranho, uma vez que na definição do SET da SQL, o nome do campo permanecia inalterado. Depois de algumas pesquisas, achei uma doc que a propriedade (veja abaixo) <code>Translate Field Names</code> era a responsável por este comportamento estranho.</p> +<p><img alt="Apache NiFi JSONToSQL config" src="/images/apache_nifi_jsontosql.png"></p> +<p>Antes de definir a propriedade como <strong>FALSE</strong>, esteja ciente que as propriedades do seu JSON devem ser exatamente iguais aos nomes dos campos da sua tabela.</p>Cool Tools2017-09-17T14:00:00-03:002017-09-17T14:00:00-03:00Maurício Camargo Sipmanntag:www.sipmann.com,2017-09-17:/pt/cool-tools.html<p>Com o passar do tempo você vai &quot;encontrando&quot; - e às vezes até mesmo desenvolvendo - algumas ferramentas que tornam o seu dia a dia como desenvolvedor mais fácil. Abaixo seguem algumas das minhas ferramentas que costumo usar. Ressalto que essa lista será (provavelmente) atualizada com o passar do tempo.</p> +<div class="section" id="https-www-gitkraken-com"> +<h2><a class="reference external" href="https://www.gitkraken.com">https://www …</a></h2></div><p>Com o passar do tempo você vai &quot;encontrando&quot; - e às vezes até mesmo desenvolvendo - algumas ferramentas que tornam o seu dia a dia como desenvolvedor mais fácil. Abaixo seguem algumas das minhas ferramentas que costumo usar. Ressalto que essa lista será (provavelmente) atualizada com o passar do tempo.</p> +<div class="section" id="https-www-gitkraken-com"> +<h2><a class="reference external" href="https://www.gitkraken.com">https://www.gitkraken.com</a></h2> +<p>Eu gosto muito de usar git, mas às vezes fico cansado de ter que usar só linha de comando, e achei no GitKreaken uma interface muito legal de se usar.</p> +</div> +<div class="section" id="http-paletton-com"> +<h2><a class="reference external" href="http://paletton.com">http://paletton.com</a></h2> +<p>Toda vez que você vai fazer um novo sistema/site, ou até mesmo trocar o layout de algum já existente, você acaba tendo que montar uma paleta de cores para se utilizar em todo o template.</p> +</div> +<div class="section" id="https-icomoon-io-app-select"> +<h2><a class="reference external" href="https://icomoon.io/app/#/select">https://icomoon.io/app/#/select</a></h2> +<p>Querendo usar ícones como fontes? Vá aí e gere apenas os arquivos que você vai realmente utilizar e economize alguns kbs.</p> +</div> +<div class="section" id="https-syncthing-net"> +<h2><a class="reference external" href="https://syncthing.net/">https://syncthing.net/</a></h2> +<p>Se você procura algum meio de sincronizar seus arquivos entre vários pcs e por algum motivo não quer usar um Google Drive ou DropBox, fica aqui a indicação deste cara.</p> +</div> +<div class="section" id="http-sqitch-org"> +<h2><a class="reference external" href="http://sqitch.org/">http://sqitch.org/</a></h2> +<p>Gerenciamento de versões de um banco de dados pode ser bem complicado e trabalhoso... Manter diversos ambientes (desenvolvimento, homologação, produção) vai dar um trabalho se não utilizar alguma ferramenta. Porque não usar o melhor de gerenciamento de versão (git) e uma ferramenta que se adequa ao que você precisa? sqitch é o cara nessas horas.</p> +</div> +<div class="section" id="http-www-setupmyproject-com"> +<h2><a class="reference external" href="http://www.setupmyproject.com/">http://www.setupmyproject.com/</a></h2> +<p>Preparação de projetos java, com frameworks, bibliotecas, nomenclatura, etc... Rende uma economia de tempo grandiosa e já vem tudo pronto :).</p> +</div> +<div class="section" id="https-www-pexels-com"> +<h2><a class="reference external" href="https://www.pexels.com/">https://www.pexels.com/</a></h2> +<p>Bom site para imagens free stock. Excelente local para conseguir imagens de alta qualidade.</p> +</div> +<div class="section" id="https-heml-io"> +<h2><a class="reference external" href="https://heml.io/">https://heml.io/</a></h2> +<p>&quot;HEML is an open source markup language for building responsive email.&quot; Melhor descrição impossível.</p> +</div> +<div class="section" id="https-www-mockapi-io"> +<h2><a class="reference external" href="https://www.mockapi.io/">https://www.mockapi.io/</a></h2> +<p>Desenvolva mocks para testar seu front-end. Eles geram inclusive uma carga de dados para ser utilizado nos seus testes.</p> +</div> +<div class="section" id="https-undraw-co"> +<h2><a class="reference external" href="https://undraw.co">https://undraw.co</a></h2> +<p>Needing some cool and free ilustrations? Take a look at it.</p> +</div> +<div class="section" id="https-www-audiotool-com-app"> +<h2><a class="reference external" href="https://www.audiotool.com/app/">https://www.audiotool.com/app/</a></h2> +<p>Ferramenta para criar sons, musicas e afins</p> +</div> +<div class="section" id="https-app-cloudskew-com"> +<h2><a class="reference external" href="https://app.cloudskew.com/">https://app.cloudskew.com/</a></h2> +<p>Desenhar projetos de cloud e afins</p> +</div> +<div class="section" id="https-lottiefiles-com"> +<h2><a class="reference external" href="https://lottiefiles.com/">https://lottiefiles.com/</a></h2> +<p>Veja por si mesmo</p> +</div> + \ No newline at end of file diff --git a/pt/feeds/tools.atom.xml.gz b/pt/feeds/tools.atom.xml.gz new file mode 100644 index 000000000..85acb91b9 Binary files /dev/null and b/pt/feeds/tools.atom.xml.gz differ diff --git a/pt/index.html b/pt/index.html new file mode 100644 index 000000000..b406f84aa --- /dev/null +++ b/pt/index.html @@ -0,0 +1,603 @@ + + + + + + + + Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+ +
+
+
+

Apache Nifi JSON to SQL removendo underline

+
+ +
+
+ +
+

Recentemente eu estava desenvolvendo alguns processos de ETL com o Apache NiFi. Mas após alguns minutos desenhando o meu fluxo, eu vi um comportamento estranho do componente ConvertJSONToSQL, que estava substituindo os underline ('_') do nome de um campo utilizado na condição da SQL (eu estava preparando um UPDATE). Aquilo …

+
+ + + +
+
+
+
+ +
+
+ + + + + + + +
+

Então, você utiliza Entity Framework Core e geralmente faz o seu selecto da seguinte forma, talvez você está retornando muitos dados.

+
var products = Products
+    .Where(p => p.UnitsInStock > 0)
+    .OrderBy(p => p.ProductName)
+    .ToList()
+
+ +

Rodando a query acima, em uma base de testes você obtem o seguinte resultado, veja quantas …

+
+ + + +
+
+
+
+
+ + + + + +
+

Zabbix Running on Low Memory Mode

+
+ +
+
+ +
+

Olá pessoal! Trago hoje outro post sobre Zabbix. Este é sobre aumentar o cache do seu Zabbix Server. É perfeitamente comum (se você roda com as configurações padrões) receber avisos sobre Zabbix value cache running on low memory mode no seu dashboard ou arquivos de log.

+

Zabbix Dashboard alertando sobre problemas de memória +Zabbix Dashboard cache gráfico com 70% utilizado

+

Para resolver, abra o …

+
+ + + +
+
+
+
+
+ + + + + + + +
+

Tenho migrado alguns scripts bash que tenho para PowerShell, e chegou a vez de migrar um script de monitoramento de replicação do MySQL. Fica como crédito o script original do Paweł. É um script bem simples onde eu verifico algumas tags resultantes do SHOW SLAVE STATUS\G, são elas. Slave_IO_Running …

+
+ + + +
+
+
+
+
+
+

Microsoft Contra Covid

+
+ +
+
+ +
+

Você teve seu trabalho afetado pela pandemia do covid? Bom, na última semana eu postei no Grepora sobre um Voucher para certificação gratuita que a Microsoft estava distribuindo durante o evento Microsoft Ignite. Depois disto, eu fiquei sabendo que eles também estão entregando grandes discontos para quem teve o seu …

+
+ + + +
+
+
+
+
+ + + + + +
+

O poder do PowerShell

+
+ +
+
+ +
+

Como um usuário linux por muito tempo, eu automatizei algumas tarefas com scripts bash e fiquei longe do PowerShell... Voltei a utilizar Windows alguns anos atrás e ainda assim, não dei uma chance ao PS. Mas porque não? Eu fiz alguns scripts para automatizar algumas tarefas em um servidor Protheus …

+
+ + + +
+
+
+
+
+ + + + + +
+

Top Level Statement no C# 9

+
+ +
+
+ +
+

Olá pessoal, venho hoje falar sobre uma novidade que estará disponível na versão 9 do C#. Toda vez que você deseja criar um novo projeto, você sempre tem o mesmo arquivo Main, com a mesma estrutura. Na próxima versão do C# (versão 9), nós teremos uma nova funcionalidade chamada Top …

+
+ + + +
+
+
+
+
+ + 1 + 2 + 3 + » + +
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/index.html.gz b/pt/index.html.gz new file mode 100644 index 000000000..5eb1443fc Binary files /dev/null and b/pt/index.html.gz differ diff --git a/pt/index2.html b/pt/index2.html new file mode 100644 index 000000000..8693f1218 --- /dev/null +++ b/pt/index2.html @@ -0,0 +1,574 @@ + + + + + + + + Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Zabbix poller processes more than 75%

+
+ +
+
+ +
+

Este é o terceiro post sobre configurações para o Zabbix. Todas as alterações que eu sugiro nestes posts, são baseadas em um servidor com 50+ hosts. Outro problema que pode ocorrer em seu servidor, é o poller de informações ficar sobrecarregado pela quantidade de servidores que ele precisa pegar carga …

+
+ + + +
+
+
+
+
+ + + + + + + +
+

Algumas vezes você se depara com a necessidade de monitorar a disponibilidade de um website ou mudanças em seu conteúdo. É claro que temos diversas opções disponíveis no mercado, mas para fins de curiosidade, vamos programar o nosso próprio e ver o que podemos fazer. Primeiramente, tudo que você ver …

+
+ + + +
+
+
+
+
+
+

Zabbix ICMP pinger processes more than 75%

+
+ +
+
+ +
+

Então o seu systema de monitoramento creasceu e o seu Zabbix começou a printar "Zabbix icmp pinger processes more than 75% busy" no seu dashboard.

+

Dashboard do zabbix avisando sobre o erro

+

Tudo que você tem a fazer é abrir o seu arquivo de configuração (/etc/zabbix/zabbix_server.conf) e localizar a tag chamada StartPingers. Ela deve …

+
+ + + +
+
+
+
+
+
+

Zabbix Server Out of Memory

+
+ +
+
+ +
+

Você tem um servidor Zabbix crashando e observando o arquivo de log /var/log/zabbix/zabbix_server.log você localiza a seguinte mensagem referênciando falta de memória?

+
__mem_malloc: skipped 0 asked 24 skip_min 18446744073709551615 skip_max 0
+[file:dbconfig.c,line:94] __zbx_mem_realloc(): out of memory (requested 16 bytes)
+[file:dbconfig.c …

+
+ + + +
+
+
+
+
+
+

Removendo um usuário de uma base SQL Server

+
+ +
+
+ +
+

O seu cliente lhe pede com urgência para dropar um usuário da sua base MsSQL Server, mas você trava com o seguinte aviso de erro:

+
Error: 15138 The database principal owns a schema in the database, and cannot be dropped.
+
+ +

Se você não possui (ou no momento não consegue acesso …

+
+ + + +
+
+
+
+ +
+
+
+

Menu dinâmico com as apps do django

+
+ +
+
+ +
+

Digamos que sua empresa trabalha com Django desenvolvendo aplicações cujas apps são plugaveis e reutilizáveis. Por que não se aproveitar de um certo padrão de desenvolvimento para desenvolver menus que se modificam de acordo com as apps que estão no projeto? Como o objetivo aqui não é desenvolver uma app …

+
+ + + +
+
+
+
+
+
+

Scripts de inicialização no raspberry pi

+
+ +
+
+ +
+

Instalei essa semana o gitea no meu raspberry pi B + e queria iniciar ele no boot... Não sou profundo conhecedor de linux, então, logo não sabia como fazer isto da melhor forma. +As versões atuais do Raspbian utilizam o systemd para gerenciar os serviços e confesso que nunca havia utilizado …

+
+ + + +
+
+
+
+
+
+

Cool Tools

+
+ +
+
+ +
+

Com o passar do tempo você vai "encontrando" - e às vezes até mesmo desenvolvendo - algumas ferramentas que tornam o seu dia a dia como desenvolvedor mais fácil. Abaixo seguem algumas das minhas ferramentas que costumo usar. Ressalto que essa lista será (provavelmente) atualizada com o passar do tempo.

+

+
+ + + +
+
+
+
+
+
+

Desenvolvendo apps para o FirefoxOS (Parte 1)

+
+ +
+
+ +
+

Requisitos mínimos?

+

Para seguir este tutorial você precisará do Nodejs. Utilizaremos ele para automatizar algumas tarefas, como a criação do nosso projeto e até mesmo o empacotamento da app. Estas automatizações se darão pela utilização de algumas aplicações como o Yeoman e o Grunt .

+

Também será necessário o emulador do …

+
+ + + +
+
+
+
+
+ « + + 1 + 2 + 3 + » + +
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/index2.html.gz b/pt/index2.html.gz new file mode 100644 index 000000000..e8fc1d1a3 Binary files /dev/null and b/pt/index2.html.gz differ diff --git a/pt/index3.html b/pt/index3.html new file mode 100644 index 000000000..907c0b372 --- /dev/null +++ b/pt/index3.html @@ -0,0 +1,333 @@ + + + + + + + + Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Editando o Admin do Django

+
+ +
+
+ +
+

Este artigo foi re-postado no grupo PythonClub. Vamos falar um pouco sobre como customizar o admin do Django. Primeiramente porque? A resposta é bem simples, quero mostrar algo para o usuário sem que ele precise entrar nas apps e fazer alguma consulta para então tomar alguma ação. Alguns exêmplos para …

+
+ + + +
+
+
+
+
+ « + + 1 + 2 + 3 + +
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/index3.html.gz b/pt/index3.html.gz new file mode 100644 index 000000000..40a7a8e2f Binary files /dev/null and b/pt/index3.html.gz differ diff --git a/pt/menu-dinamico-com-apps-do-django.html b/pt/menu-dinamico-com-apps-do-django.html new file mode 100644 index 000000000..5f44d2ad9 --- /dev/null +++ b/pt/menu-dinamico-com-apps-do-django.html @@ -0,0 +1,562 @@ + + + + + + + + Menu dinâmico com as apps do django - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Menu dinâmico com as apps do django

+
+ +
+
+ +
+

Digamos que sua empresa trabalha com Django desenvolvendo aplicações cujas apps são plugaveis e reutilizáveis. Por que não se aproveitar de um certo padrão de desenvolvimento para desenvolver menus que se modificam de acordo com as apps que estão no projeto? Como o objetivo aqui não é desenvolver uma app em si, vamos utilizar um projeto com algumas de modelo. Se desejar estudar mais sobre desenvolvimento Django, a documentação é muito boa, mas também temos blogs e sites excelentes sobre o assunto.

+

Para conseguirmos atingir esse objetivo, vamos utilizar a api Django.apps que está disponível a partir da versão 1.7. +Com esta api, vamos percorrer as apps e se possível, criar um link para uma URL base de cada uma delas. Para começo, baixe os fontes do projeto aqui, rode o pip install do projeto e no fim, sua estrutura de pastas deve ficar como abaixo.

+
../menusapp/
+├── comentarios
+│   ├── templates
+│   │   └── comentarios
+│   │      └── listagem.html
+│   ├── __init__.py
+│   ├── admin.py
+│   ├── apps.py
+│   ├── models.py
+│   ├── tests.py
+│   ├── urls.py
+│   └── views.py
+├── core
+│   ├── templates
+│   │   └── core
+│   │       └── base.html
+│   │       └── listagem.html
+│   ├── __init__.py
+│   ├── admin.py
+│   ├── apps.py
+│   ├── models.py
+│   ├── tests.py
+│   ├── urls.py
+│   └── views.py
+├── menusapp
+│   ├── __init__.py
+│   ├── settings.py
+│   ├── urls.py
+│   └── wsgi.py
+└── manage.py
+
+

Rode o projeto e veja como é o seu funcionamento. É na app core que temos a base do nosso HTML, então será nele que iremos trabalhar. Quando se trata de algo que será renderizado no template base, eu gosto muito de utilizar 'template tags' para facilitar. +Neste link tem mais um exemplo de utilização de 'template tag' caso esteja interessado.

+

Vamos então criar uma pasta chamada template_tag e dentro dela a nossa tag. Vamos chamá-la de menus_tag.py. Abaixo vamos ver um pouco da nossa tag. +O código é bem simples e auto explicativo, importamos as bibliotecas necessárias e realizamos o @register da tag com o nome do template que será renderizado. +E por ultimo, retornamos uma tupla de dados para o template.

+
+
Recomendações
+ + +
from django import template
+from django.apps import apps
+
+#Carrega o registro de template tags
+register = template.Library()
+
+#Registra o metodo a seguir como uma inclusion_tag indicando o template a ser renderizado
+@register.inclusion_tag('menus_por_app.html')
+def menus_por_app():
+    lst = apps.get_app_configs()
+    return { 'lst_apps' : lst }
+
+

O template está abaixo e é simplesmente um for percorrendo as apps e gerando uma lista com os seus menus. As outras propriedades você pode ver direto na documentação. +Algumas ressalvas para o que foi feito por questões de praticidade para uso posterior, utilizei um with para concatenar e gerar a url e criei um apelido para a url para validar a existência da mesma. Fora isto, nada de novo.

+
{% if not lst_apps %}
+                    <p>Nenhuma app</p>
+            {% else %}
+                    <ul>
+                            {% for app in lst_apps %}
+                                    {% with app.name|add:":listagem" as link %}
+                                            {% url link as the_url %}
+                                                    {% if the_url %}
+                                                    <li>
+                                                            <a href="{% url link %}">{{ app.verbose_name|truncatechars:30 }}</a>
+                                                    </li>
+                                                    {% endif %}
+                                    {% endwith %}
+                            {% endfor %}
+                    </ul>
+            {% endif %}
+
+Resultado final +

No final, o resultado obtido deve ser semelhante ao acima. Repare que está listando as duas aplicações. E acima de tudo, repare que só serão exibidos os links cuja app tenha um namespace de mesmo nome e uma url de nome listagem. +A estrutura final pode ser vista abaixo. Atente-se aos nomes tanto das pastas quanto dos arquivos, pois qualquer diferença pode causar o não funcionamento.

+
../menusapp/
+├── comentarios
+│   ├── templates
+│   │   └── comentarios
+│   │      └── listagem.html
+│   ├── __init__.py
+│   ├── admin.py
+│   ├── apps.py
+│   ├── models.py
+│   ├── tests.py
+│   ├── urls.py
+│   └── views.py
+├── core
+│   ├── templates
+│   │   └── core
+│   │   │   └── base.html
+│   │   │   └── listagem.html
+│   │   └── menus_por_app.html
+│   ├── templatetags
+│   │   ├── __init__.py
+│   │   └── menus_tag.py
+│   ├── __init__.py
+│   ├── admin.py
+│   ├── apps.py
+│   ├── models.py
+│   ├── tests.py
+│   ├── urls.py
+│   └── views.py
+├── menusapp
+│   ├── __init__.py
+│   ├── settings.py
+│   ├── urls.py
+│   └── wsgi.py
+└── manage.py
+
+

Espero que tenham gostado, críticas e sugestões são bem-vindas. Fontes do Projeto

+

+
+ + +
+
+

Traduções:

+
    +
+
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/menu-dinamico-com-apps-do-django.html.gz b/pt/menu-dinamico-com-apps-do-django.html.gz new file mode 100644 index 000000000..30647e42e Binary files /dev/null and b/pt/menu-dinamico-com-apps-do-django.html.gz differ diff --git a/pt/microsoft-against-covid.html b/pt/microsoft-against-covid.html new file mode 100644 index 000000000..ce207e96f --- /dev/null +++ b/pt/microsoft-against-covid.html @@ -0,0 +1,482 @@ + + + + + + + + Microsoft Contra Covid - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Microsoft Contra Covid

+
+ +
+
+ +
+

Você teve seu trabalho afetado pela pandemia do covid? Bom, na última semana eu postei no Grepora sobre um Voucher para certificação gratuita que a Microsoft estava distribuindo durante o evento Microsoft Ignite. Depois disto, eu fiquei sabendo que eles também estão entregando grandes discontos para quem teve o seu trabalho afetado pela pandemia do covid.

+

Para saber se você pode receber este desconto, acesse https://docs.microsoft.com/en-us/learn/certifications/skillingoffer.

+
+ + +
+
+

Traduções:

+ +
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/microsoft-against-covid.html.gz b/pt/microsoft-against-covid.html.gz new file mode 100644 index 000000000..ddcc453d8 Binary files /dev/null and b/pt/microsoft-against-covid.html.gz differ diff --git a/pt/monitoring-mysql-replication-with-powershell.html b/pt/monitoring-mysql-replication-with-powershell.html new file mode 100644 index 000000000..e69d47c3d --- /dev/null +++ b/pt/monitoring-mysql-replication-with-powershell.html @@ -0,0 +1,547 @@ + + + + + + + + Monitorando status de replicação do MySQL com PowerShell - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+ + +
+

Tenho migrado alguns scripts bash que tenho para PowerShell, e chegou a vez de migrar um script de monitoramento de replicação do MySQL. Fica como crédito o script original do Paweł. É um script bem simples onde eu verifico algumas tags resultantes do SHOW SLAVE STATUS\G, são elas. Slave_IO_Running, Slave_SQL_Running e Seconds_Behind_Master. Ainda preciso verificar formas mais corretas de armazenar/carregar as variáveis como usuários e senha, se tiver alguma dica, fique à vontade para inclusive fazer um pull request (aqui) no repositório onde vou armazenar alguns dos meus scripts.

+
<#
+   Variables definition
+#>
+$MaxSeconds = 120  # Max seconds behind master allowed
+$MysqlUser  = 'root'
+$MysqlPass  = ''
+
+$MailTo     = 'mauricio@sipmann.com'
+$MailFrom   = 'mauricio@sipmann.com'
+
+
+$data = $(mysql -u $MysqlUser -p"$MysqlPass" -e 'SHOW SLAVE STATUS \G')
+
+#Debug data
+#$data = Get-Content 'c:\temp\sampleresult.txt'
+
+<# Parse the data #>
+$IORunning   = (($data | Where-Object { $_ -match 'Slave_IO_Running:' }) -split '\s+')[2]
+$SQLRunning  = (($data | Where-Object { $_ -match 'Slave_SQL_Running:' }) -split '\s+')[2]
+$LastErrNo   = (($data | Where-Object { $_ -match 'Last_Errno' }) -split '\s+')[2]
+$SecondsBh   = [int](($data | Where-Object { $_ -match 'Seconds_Behind_Master' }) -split '\s+')[2]
+
+If ($IORunning -Eq 'No' -Or $SQLRunning -Eq 'No' -Or $SecondsBh -gt $MaxSeconds) {
+    $MailBody = '<h1>Problema na replicação</h1><br>'
+
+    $MailBody += '    IO Running: ' + ($IORunning)  + '<br>'
+    $MailBody += '   SQL Running: ' + ($SQLRunning) + '<br>'
+    $MailBody += 'Seconds Behind: ' + ($SecondsBh) + '<br>'
+    $MailBody += '   Last Err No: ' + ($LastErrNo) + '<br>'
+
+    <# Send e-mail, maybe some telegram message here too #>
+    Send-MailMessage -To $MailTo -From $MailFrom  -Subject 'Problemas na replicação' -bodyAsHtml $MailBody -Credential (Get-Credential) -SmtpServer 'smtp.office365.com' -Port 587 -UseSsl
+} Else {
+    Write-Host "Up and running"
+}
+

+
+ + +
+
+

Traduções:

+ +
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/monitoring-mysql-replication-with-powershell.html.gz b/pt/monitoring-mysql-replication-with-powershell.html.gz new file mode 100644 index 000000000..29d25c1ac Binary files /dev/null and b/pt/monitoring-mysql-replication-with-powershell.html.gz differ diff --git a/pt/monitoring-mysql-restarts-with-powershell.html b/pt/monitoring-mysql-restarts-with-powershell.html new file mode 100644 index 000000000..cbcfc9ac9 --- /dev/null +++ b/pt/monitoring-mysql-restarts-with-powershell.html @@ -0,0 +1,511 @@ + + + + + + + + Monitorando restarts do MySQL com PowerShell - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Monitorando restarts do MySQL com PowerShell

+
+ +
+
+ +
+

Bom, chegou a hora para mais um script PowerShell. Se você ainda não viu os outros, de uma olhada no link abaixo.

+ +

Este aqui é um script bem simples, mas novamente, se seu cliente não possui um servidor Zabbix ou não permite que você configure um para realizar este monitoramento, um conjunto de scripts pode ser bem útil. Primeiramente nós executamos uma query báscia SHOW GLOBAL STATUS LIKE 'Uptime', com ela nós conseguimos capturar exatamente o que nós estamos procurando.

+

Se por alguma razão o comando falhar (verificamos atravez da variábel global $lastExitCode), nós mandamos um e-mail lhe avisando sobre o problema ocorrido.

+

E então, nós chegamos à parte onde fazemos o parse do valor obtido, esta parte é bem similar ao parse que codificamos no primeiro post sobre monitoramento utilizando PowerShell. Nós basicamentes procuramos pela linha contendo Value, separamos por espaço e então parseamos a segunda posição em um inteiro. Então tudo que precisamos fazer é verificar se o valor parseado é menor que o nosso threshold, se for menor, nós mandamos um e-mail.

+
$MailFrom = 'maurio[at]sipmann.com'
+$MailTo   = 'mauricio[at]sipmann.com'
+$MysqlHost = '127.0.0.1'
+$MysqlUser = 'root'
+$MysqlPass = '123'
+
+
+$data = $(mysql -h $MysqlHost -u $MysqlUser -p"$MysqlPass" -e "SHOW GLOBAL STATUS LIKE 'Uptime' \G")
+
+<# Unable to execute the sql Command #>
+if ($lastExitCode -eq 1) {
+    Send-MailMessage -To $MailTo -From $MailFrom  -Subject 'Connection problem' -bodyAsHtml "Connection problem on host ${MysqlHost}" -Credential Get-Credential -SmtpServer 'smtp.office365.com' -Port 587 -UseSsl
+    exit
+}
+
+$UpTime   = [int](($data | Where-Object { $_ -match 'Value:' }) -split '\s+')[2]
+
+<# If the uptime is lower then 20 minutes #>
+if ($UpTime -lt 1200) {
+    Send-MailMessage -To $MailTo -From $MailFrom -Subject "MySQL Restarted" -bodyAsHtml "MySQL host ${MysqlHost} restarted less than 20 minutes ago" -Credential Get-Credential -SmtpServer 'smtp.office365.com' -Port 587 -UseSsl
+}
+
+ +

Este script (e os outros que eu utilizo) estão disponíveis no meu GitHub aqui. Tenha em mente que os scripts localizados no GitHub, são um pouco diferentes do que exibido aqui. Espero que tenha achado útil.

+
+ + +
+
+

Traduções:

+ +
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/monitoring-mysql-restarts-with-powershell.html.gz b/pt/monitoring-mysql-restarts-with-powershell.html.gz new file mode 100644 index 000000000..d7e299bab Binary files /dev/null and b/pt/monitoring-mysql-restarts-with-powershell.html.gz differ diff --git a/pt/monitoring-website-heath-with-azure-functions.html b/pt/monitoring-website-heath-with-azure-functions.html new file mode 100644 index 000000000..cbfbab41d --- /dev/null +++ b/pt/monitoring-website-heath-with-azure-functions.html @@ -0,0 +1,591 @@ + + + + + + + + Monitorando a disponibilidade de um Website com Azure Functions - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+ + +
+

Algumas vezes você se depara com a necessidade de monitorar a disponibilidade de um website ou mudanças em seu conteúdo. É claro que temos diversas opções disponíveis no mercado, mas para fins de curiosidade, vamos programar o nosso próprio e ver o que podemos fazer. Primeiramente, tudo que você ver aqui, você pode utilizar o tier gratuito da Azure.

+

A ideia principal da nossa aplicação vai ser monitorar a disponibilidade do website (status code). Para criar um projeto de Azure Function, siga os passos abaixo.

+

Passos para criar um projeto Azure Functions

+

Depois de criar o projeto, você vai ter alguns arquivos. Abra o arquivo principal (HttpCheck.cs no meu caso) e começe a programar. O arquivo principal terá uma função chamada Run e você pode progamar nela o seu request. Eu criei um método async para fazer as requisições e printar a saída diretamente no console. O código completo pode ser visto abaixo.

+
using System;
+using System.Linq;
+using System.Net.Http;
+using System.Threading.Tasks;
+using Microsoft.Azure.WebJobs;
+using Microsoft.Azure.WebJobs.Host;
+using Microsoft.Extensions.Logging;
+
+namespace Sipmann.CheckMySite
+{
+    public static class HttpCheck
+    {
+
+        private static async Task GetTask(string url, ILogger log)
+        {
+            var request = new HttpRequestMessage(HttpMethod.Get, url);
+
+            var client = new HttpClient();
+            var response = await client.SendAsync(request);
+
+            if (response.IsSuccessStatusCode)
+            {
+                log.LogInformation($"URL ${url} esta OK");
+            }
+            else
+            {
+                log.LogInformation($"URL ${url} não esta OK");
+            }
+        }
+
+        [FunctionName("HttpCheck")]
+        public static void Run([TimerTrigger("0 */5 * * * *")]TimerInfo myTimer, ILogger log)
+        {
+            // URL a verificar a saúde
+            var urls = new[]{"https://www.sipmann.com", "https://www.canezecanez.com.br"};
+
+            // Starta cada request e aguarda todos de uma vez só
+            Task.WaitAll(urls.Select(url => GetTask(url, log)).ToArray());
+            log.LogInformation($"Finalizou a fila");
+        }
+    }
+}
+
+ +

Agora você pode melhorar a função e talvez enviar alguns alertas. Como por exêmplo mensagens no Telegram quando um dos sites ficar off (status code 404).

+
+ + +
+
+

Traduções:

+ +
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/monitoring-website-heath-with-azure-functions.html.gz b/pt/monitoring-website-heath-with-azure-functions.html.gz new file mode 100644 index 000000000..aeaf0ef64 Binary files /dev/null and b/pt/monitoring-website-heath-with-azure-functions.html.gz differ diff --git a/pt/mysql-dual-password-functionality.html b/pt/mysql-dual-password-functionality.html new file mode 100644 index 000000000..ad8bac1cd --- /dev/null +++ b/pt/mysql-dual-password-functionality.html @@ -0,0 +1,491 @@ + + + + + + + + Trocando a senha de um usuário do MySQL sem downtime da aplicação - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+ + +
+

Você deseja trocar a senha de um usuário do MySQL que está sendo utilizado por uma aplicação e não sofrer nenhum downtime? Bom, a versão 8.0.14 do MySQL foi liberada com uma feature chamada Dual Password Support, com esta feature você pode alterar a senha de um usuário mantendo a anterior ainda funcionando como uma forma de "backup". Desta forma, você ainda conseguirá autenticar com o usuário utilizando tanto a nova senha, quanto a anterior. Com isto, o seu processo de troca de senha fica algo como:

+

1) Troque a senha mantendo a anterior;

+

2) Faça o Deploy da nova configuração na sua aplicação/cluster;

+

3) Descarte a senha anterior.

+

Para alterar a senha mantendo a anterior, você deve rodar o seguinte comando:

+
ALTER USER 'appuser'@'localhost' IDENTIFIED BY 'new_password' RETAIN CURRENT PASSWORD;
+
+ +

Para descartar a senha antiga, rode o seguinte:

+
ALTER USER 'appuser'@'localhost' DISCARD OLD PASSWORD;
+
+ +

E pronto. Espero que isto lhe ajude a evitar downtimes e dores de cabeça :)

+
+ + +
+
+

Traduções:

+ +
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/mysql-dual-password-functionality.html.gz b/pt/mysql-dual-password-functionality.html.gz new file mode 100644 index 000000000..c7ca5088d Binary files /dev/null and b/pt/mysql-dual-password-functionality.html.gz differ diff --git a/pt/pages/about-en.html b/pt/pages/about-en.html new file mode 100644 index 000000000..4037b0e20 --- /dev/null +++ b/pt/pages/about-en.html @@ -0,0 +1,304 @@ + + + + + + + + About - Sipmann + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+

About

+ +
+ +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/pages/about-en.html.gz b/pt/pages/about-en.html.gz new file mode 100644 index 000000000..95feb801f Binary files /dev/null and b/pt/pages/about-en.html.gz differ diff --git a/pt/pages/cartao.html b/pt/pages/cartao.html new file mode 100644 index 000000000..b25d392aa --- /dev/null +++ b/pt/pages/cartao.html @@ -0,0 +1,480 @@ + + + + + + + + cartao - Sipmann + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+

cartao

+ +
+ + +
+
+ +
+
+
+
+

Consultoria Cloud

+

+ Projetos de implantação e acompanhamento de sua cloud. Otimize seus custos de infraestrutura levando o seu DR para a nuvem da forma mais transparente. +

+

Mais Detalhes

+
+
+
+
+
+
+ +
+
+
+
+

Gestão De Banco

+

+ Gerenciamento, manutenção e acompanhamento do seu banco de dados SQL Server. Com foco na segurança e velocidade de resposta em consultas. +

+

Mais Detalhes

+
+
+
+
+
+
+ +
+
+
+
+

Power BI

+

+ Dashboards analíticos para análise e tomadas de decisões do seu negócio. Baixe um dashboard e analise o faturamento do seu ERP Protheus. +

+

Mais Detalhes

+
+
+
+
+
+
+ +
+
+
+
+

Monitoramento

+

+ Monitoramento de sua infraestrutura, aplicações e bancos de dados. Fornecendo relatórios detalhados desde avisos, erros até o uptime de serviços críticos. +

+

Mais Detalhes

+
+
+
+
+
+
+ +
+
+

Consultoria cloud

+
+
+

+
+
+ +
+
+

Meus Serviços

+
+
+

Has your job been affected by covid? Well, last week I've posted on Grepora about a Free Certification Voucher that Microsoft was giving away at the Microsoft Ignite event. After that, I found that they were also giving a huge discount to people who have had their job affected by …

+
+ + +
+

+ View comments +

+
+
+
+
+ + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/pages/cartao.html.gz b/pt/pages/cartao.html.gz new file mode 100644 index 000000000..7e9348502 Binary files /dev/null and b/pt/pages/cartao.html.gz differ diff --git a/pt/removing-user-from-sql-server-database.html b/pt/removing-user-from-sql-server-database.html new file mode 100644 index 000000000..ab0f69d69 --- /dev/null +++ b/pt/removing-user-from-sql-server-database.html @@ -0,0 +1,481 @@ + + + + + + + + Removendo um usuário de uma base SQL Server - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Removendo um usuário de uma base SQL Server

+
+ +
Modificado: 21 October 2020 +
+
+ +
+

O seu cliente lhe pede com urgência para dropar um usuário da sua base MsSQL Server, mas você trava com o seguinte aviso de erro:

+
Error: 15138 The database principal owns a schema in the database, and cannot be dropped.
+
+ +

Se você não possui (ou no momento não consegue acesso) ao SSMS (SQL Server Management Studio) para verificar quais schemas ou objetos o usuário é "dono", a seguinte SQL vai resolver o problema.

+
USE [DATABASENAME]
+GO
+
+select so.name Objeto, su.name Owner
+from sys.schemas so
+inner join sysusers su on so.principal_id = su.uid
+where su.name = 'username'
+
+select so.name Objeto, su.name Owner, so.xtype Tipo
+from sys.sysobjects so
+inner join sysusers su on so.uid = su.uid
+where su.name = 'username'
+
+ +

Assim que você tiver os objetos/schemas que o usuário é dono, você pode alterar os mesmos com a seguinte SQL (exemplo de troca de schema):

+
USE [DATABASENAME]
+GO
+ALTER AUTHORIZATION ON SCHEMA::[db_datareader] TO [dbo] -- username do novo dono
+ALTER AUTHORIZATION ON SCHEMA::[db_datawriter] TO [dbo]
+GO
+
+ +

Então, você pode dropar o usuário DROP USER [username].

+
+ + +
+
+

Traduções:

+ +
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/removing-user-from-sql-server-database.html.gz b/pt/removing-user-from-sql-server-database.html.gz new file mode 100644 index 000000000..50fdf3159 Binary files /dev/null and b/pt/removing-user-from-sql-server-database.html.gz differ diff --git a/pt/script-de-inicializacao-raspberry.html b/pt/script-de-inicializacao-raspberry.html new file mode 100644 index 000000000..db2ef9e06 --- /dev/null +++ b/pt/script-de-inicializacao-raspberry.html @@ -0,0 +1,543 @@ + + + + + + + + Scripts de inicialização no raspberry pi - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Scripts de inicialização no raspberry pi

+
+ +
+
+ +
+

Instalei essa semana o gitea no meu raspberry pi B + e queria iniciar ele no boot... Não sou profundo conhecedor de linux, então, logo não sabia como fazer isto da melhor forma. +As versões atuais do Raspbian utilizam o systemd para gerenciar os serviços e confesso que nunca havia utilizado o systemctl para nada.

+

Vamos começa criando um arquivo de serviço dentro da pasta /etc/systemd/system, vale ressaltar que a pasta system deve (em teoria) ser reservada para pacotes do sistema. +Vamos criar o arquivo com o nome gitea.service dentro da pasta antes mencionada. Abaixo podemos ver como ficou o arquivo e um detalhamento após ele.

+
[Unit]
+Description=Gitea Service
+After=network.target
+
+[Service]
+Type=simple
+User=root
+WorkingDirectory=/root/
+ExecStart=/root/gitea web
+Restart=on-abort
+
+

A composição do arquivo é bem simples, mas vamos a alguns detalhes. Type possui várias opções (simple, forking, oneshot), utilizamos simple uma vez que o nosso processo executara, permanecerá rodando e não executa um fork de processo. +Fork como acabo de comentar, deve ser utilizado caso o processo que for executando disparar mais processos. User irá definir o usuário do processo. WorkingDirectory definira onde o processo terá a sua base de execução, como o gitea esta localizada na pasta root, +aponto para lá. O ExecStart é bem simples e direto, deve chamar a execução do processo passando parametros caso seja necessário. O Restart é o que nos garantirá que o serviço permanecerá rodando caso haja algum imprevisto (exceto o fato de um usuário chamar o stop).

+

Salve o arquivo e vamos rodar um refresh para o SO perceber o novo serviço. Assim rodamos systemctl daemon-reload. Sempre que alterarmos um serviço ou criarmos um novo, este comando deve ser executado, caso contrário o próprio systemctl pode lhe alertar da necessidade. +Após reacarregar os serviços, vamos habilitar o serviço que criamos rodando systemctl enable gitea, feito isto temos alguns comandos uteis.

+
    +
  • systemctl start gitea
  • +
  • systemctl stop gitea
  • +
  • systemctl status gitea
  • +
+

O comando de status pode ser visto como exemplo abaixo.

+
● gitea.service - Gitea Service
+  Loaded: loaded (/etc/systemd/system/gitea.service; enabled; vendor preset: enabled)
+  Active: active (running) since Wed 2017-10-04 00:37:34 UTC; 52min ago
+Main PID: 1087 (gitea)
+  CGroup: /system.slice/gitea.service
+          └─1087 /root/gitea web
+
+Oct 04 00:38:31 gitserver gitea[1087]: [Macaron] 2017-10-04 00:38:31: Completed /explore/users 200 OK in 80.106173ms
+Oct 04 00:38:31 gitserver gitea[1087]: [Macaron] 2017-10-04 00:38:31: Started GET /img/favicon.png for 192.168.1.4
+Oct 04 00:38:31 gitserver gitea[1087]: [Macaron] [Static] Serving /img/favicon.png
+
+

Após estes processos, você pode reiniciar seu raspberry que o gitea irá subir e funcionar. Ressalto que, preste atenção tanto no WorkingDirectory quanto no ExecStart, no caso do gitea, ele utiliza o workingdir e a forma de start para saber onde irá largar os arquivos por padrão, então ou você configura ele com caminhos absolutos ou cuidar na forma de start (ao menos é o que consegui pegar até agora).

+

+
+ + +
+
+

Traduções:

+
    +
+
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/script-de-inicializacao-raspberry.html.gz b/pt/script-de-inicializacao-raspberry.html.gz new file mode 100644 index 000000000..817366c98 Binary files /dev/null and b/pt/script-de-inicializacao-raspberry.html.gz differ diff --git a/pt/select_specific_fields_with_efcore.html b/pt/select_specific_fields_with_efcore.html new file mode 100644 index 000000000..5ed77fbc0 --- /dev/null +++ b/pt/select_specific_fields_with_efcore.html @@ -0,0 +1,505 @@ + + + + + + + + Como definir as colunas no select utilizando Entity Framework - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+ + +
+

Então, você utiliza Entity Framework Core e geralmente faz o seu selecto da seguinte forma, talvez você está retornando muitos dados.

+
var products = Products
+    .Where(p => p.UnitsInStock > 0)
+    .OrderBy(p => p.ProductName)
+    .ToList()
+
+ +

Rodando a query acima, em uma base de testes você obtem o seguinte resultado, veja quantas colunas estão retornando da sua base de dados.

+

Print com todas as colunas

+

No meu caso, eu só pretendo ter de volta as colunas Title, PublishedData e uma pequena descrição. Então para selecionar apenas estes campos, nós temos algumas opções. Na primeira, nós vamos definir os campos e retornar um objeto do tipo Dynamic. A segunda forma, é dar ao .NET o objeto a ser retornado, pode ser por exêmplo um DTO.

+
var products = Products
+
+    .Select(p => new {p.ProductID, p.ProductName, p.UnitsInStock, p.UnitPrice})
+    //.Select(p => new ProductDTO {p.ProductID, p.ProductName, p.UnitsInStock, p.UnitPrice})
+
+    .Where(p => p.UnitsInStock > 0)
+    .OrderBy(p => p.ProductName)
+    .ToList()
+
+ +

Print com menos colunas e também menor quantidade de dados

+
+ + +
+
+

Traduções:

+ +
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/select_specific_fields_with_efcore.html.gz b/pt/select_specific_fields_with_efcore.html.gz new file mode 100644 index 000000000..74b62c492 Binary files /dev/null and b/pt/select_specific_fields_with_efcore.html.gz differ diff --git a/pt/sitemap.xml b/pt/sitemap.xml new file mode 100644 index 000000000..d15937b9b --- /dev/null +++ b/pt/sitemap.xml @@ -0,0 +1,650 @@ + + + + +https://www.sipmann.com/pt/ +2024-02-14T00:32:49-00:00 +daily +0.4 + + + +https://www.sipmann.com/pt/tags.html +2024-02-14T00:32:49-00:00 +daily +0.4 + + + +https://www.sipmann.com/pt/categories.html +2024-02-14T00:32:49-00:00 +daily +0.4 + + + +https://www.sipmann.com/pt/authors.html +2024-02-14T00:32:49-00:00 +daily +0.4 + + + +https://www.sipmann.com/pt/archives.html +2024-02-14T00:32:49-00:00 +daily +0.4 + + + +https://www.sipmann.com/pt/monitoring-mysql-restarts-with-powershell.html +2020-12-21T13:30:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/pt/mysql-dual-password-functionality.html +2020-12-09T13:40:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/pt/apache-nifi-json-to-sql-replacing-underscore.html +2020-12-02T14:00:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/pt/blocking-user-on-sql-server-based-on-schedule.html +2020-11-14T07:00:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/pt/select_specific_fields_with_efcore.html +2020-10-28T19:00:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/pt/zabbix-running-on-low-memory-mode.html +2020-10-20T19:00:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/pt/monitoring-mysql-replication-with-powershell.html +2020-10-14T19:00:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/pt/microsoft-against-covid.html +2020-10-03T19:00:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/pt/the-power-of-powershell.html +2020-09-21T19:00:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/pt/top_level_statement_csharp_9.html +2020-07-29T19:00:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/pt/zabbix-poller-processes-more-than-75.html +2020-07-02T19:00:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/pt/monitoring-website-heath-with-azure-functions.html +2020-06-22T19:00:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/pt/zabbix-icmp-pinger-processes-more-than-75.html +2020-05-25T16:00:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/pt/zabbix-server-out-of-memory-crash.html +2020-02-27T19:00:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/pt/removing-user-from-sql-server-database.html +2020-10-21T18:40:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/pt/socketException-protocol-family-unavailable-java-docker-wildfly.html +2018-03-04T17:40:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/pt/menu-dinamico-com-apps-do-django.html +2018-01-21T21:17:00-02:00 +monthly +0.8 + + + +https://www.sipmann.com/pt/script-de-inicializacao-raspberry.html +2017-10-08T18:00:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/pt/cool-tools.html +2017-09-17T14:00:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/pt/desenvolvendo-app-firefoxos.html +2014-09-02T19:00:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/pt/editando-o-admin-do-django.html +2014-05-15T18:00:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/pt/category/azure.html +2020-10-03T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/category/firefoxos.html +2014-09-02T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/category/java.html +2018-03-04T17:40:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/category/linux.html +2020-10-20T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/category/mysql.html +2020-12-09T13:40:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/category/net.html +2020-10-28T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/category/powershell.html +2020-12-21T13:30:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/category/python.html +2018-01-21T21:17:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/category/shell.html +2017-10-08T18:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/category/sql-server.html +2020-11-14T07:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/category/tools.html +2020-12-02T14:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/mysql.html +2020-12-21T13:30:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/mysql-restart.html +2020-12-21T13:30:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/powershell-monitoring.html +2020-12-21T13:30:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/mysql-dual-password.html +2020-12-09T13:40:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/apache-nifi.html +2020-12-02T14:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/convertjsontosql.html +2020-12-02T14:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/removendo-underline.html +2020-12-02T14:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/sqlserver.html +2020-11-14T07:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/user.html +2020-11-14T07:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/time-schedule-blocking.html +2020-11-14T07:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/dotnet.html +2020-10-28T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/dotnet-core.html +2020-10-28T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/entity-framework.html +2020-10-28T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/ef-core.html +2020-10-28T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/specify-columns.html +2020-10-28T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/zabbix.html +2020-10-20T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/shell.html +2020-10-20T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/low-memory.html +2020-10-20T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/cache.html +2020-10-20T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/mysql-replication.html +2020-10-14T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/powershell.html +2020-10-14T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/powershell-mail.html +2020-10-14T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/azure.html +2020-10-03T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/certification.html +2020-10-03T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/microsoft.html +2020-10-03T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/script.html +2020-09-21T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/getchild-item.html +2020-09-21T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/remove-item.html +2020-09-21T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/stop-proccess.html +2020-09-21T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/c.html +2020-07-29T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/net.html +2020-07-29T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/zabbix-poller.html +2020-07-02T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/poller-proccess.html +2020-07-02T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/azure-devops.html +2020-06-22T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/monitor-website.html +2020-06-22T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/icmp-pinger.html +2020-05-25T16:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/icmp-pinger-more-than-75.html +2020-05-25T16:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/zabbix-server.html +2020-05-25T16:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/out-of-memory.html +2020-02-27T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/crash.html +2020-02-27T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/the-database-principal-owns-a-schema.html +2020-10-21T18:40:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/java.html +2018-03-04T17:40:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/wildfly.html +2018-03-04T17:40:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/docker.html +2018-03-04T17:40:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/javanetsocketexception.html +2018-03-04T17:40:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/protocol-family-unavailable.html +2018-03-04T17:40:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/python.html +2018-01-21T21:17:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/django.html +2018-01-21T21:17:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/raspberry.html +2017-10-08T18:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/tools.html +2017-09-17T14:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/firefoxos.html +2014-09-02T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/html.html +2014-09-02T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/yeoman.html +2014-09-02T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/tag/django-admin.html +2014-05-15T18:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/pt/author/mauricio-camargo-sipmann.html +2020-12-21T13:30:00-03:06 +daily +0.4 + + + diff --git a/pt/sitemap.xml.gz b/pt/sitemap.xml.gz new file mode 100644 index 000000000..5a9014835 Binary files /dev/null and b/pt/sitemap.xml.gz differ diff --git a/pt/socketException-protocol-family-unavailable-java-docker-wildfly.html b/pt/socketException-protocol-family-unavailable-java-docker-wildfly.html new file mode 100644 index 000000000..b08f76d27 --- /dev/null +++ b/pt/socketException-protocol-family-unavailable-java-docker-wildfly.html @@ -0,0 +1,446 @@ + + + + + + + + Resolvendo java.net.SocketException: Protocol family unavailable em Java + Docker + WildFly - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+ + +
+

Nos últimos dias eu estou brincando com o WildFly Swarm e decidi fazer o deploy de uma aplicação simples com Docker. Deveria funcionar bem, ao menos é o que pensava. Construí um container com o seguinte Dockerfile e ao invés de obter uma aplicação web, tudo que eu obtive foi o erro java.net.SocketException: Protocol family unavailable.

+
FROM java:openjdk-8-jdk
+
+COPY target/issues.jar /opt/issues.jar
+
+EXPOSE 8080
+
+CMD ["java","-jar","/opt/issues.jar"]
+
+

Por alguma razão, WildFly e Java, ambos decidiram utilizar um protocolo IPv6 na interface de rede no Docker invés da v4, então tudo que você tem que fazer é falar ao Java que deve dar preferência em utilizar o IPv4 com a seguinte configuração no seu arquivo pom.xml dentro da tag do plugin WildFly.

+
<plugin>
+        <groupId>org.wildfly.swarm</groupId>
+        <artifactId>wildfly-swarm-plugin</artifactId>
+        <version>2018.2.0</version>
+
+        <!-- ADICIONE ISTO -->
+        <configuration>
+          <mainClass>org.wildfly.swarm.examples.netflix.ribbon.frontend.Main</mainClass>
+          <properties>
+                <java.net.preferIPv4Stack>true</java.net.preferIPv4Stack>
+          </properties>
+        </configuration>
+
+

Outra forma de solucionar o problema, é adicionando a mesma propriedade ao comando de run no seu Dockerfile. Então, fica a seu critério onde adicionar. Abaixo a solução utilizando o Dockerfile.

+
FROM java:openjdk-8-jdk
+ENV JAVA_OPTS="-Djava.net.preferIPv4Stack=true -Djava.net.preferIPv4Addresses=true"
+
+COPY target/issues.jar /opt/issues.jar
+
+EXPOSE 8080
+
+ENTRYPOINT exec java $JAVA_OPTS -jar /opt/issues.jar
+
+

+
+ + +
+
+

Traduções:

+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/socketException-protocol-family-unavailable-java-docker-wildfly.html.gz b/pt/socketException-protocol-family-unavailable-java-docker-wildfly.html.gz new file mode 100644 index 000000000..ca04939cd Binary files /dev/null and b/pt/socketException-protocol-family-unavailable-java-docker-wildfly.html.gz differ diff --git a/pt/tag/apache-nifi.html b/pt/tag/apache-nifi.html new file mode 100644 index 000000000..0698c36ee --- /dev/null +++ b/pt/tag/apache-nifi.html @@ -0,0 +1,296 @@ + + + + + + + + Apache Nifi - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Apache Nifi

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/apache-nifi.html.gz b/pt/tag/apache-nifi.html.gz new file mode 100644 index 000000000..c1cba1e26 Binary files /dev/null and b/pt/tag/apache-nifi.html.gz differ diff --git a/pt/tag/arraymap.html b/pt/tag/arraymap.html new file mode 100644 index 000000000..44094c158 --- /dev/null +++ b/pt/tag/arraymap.html @@ -0,0 +1,286 @@ + + + + + + + + ArrayMap - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

ArrayMap

+
+ +
+
    +
+
+
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/arraymap.html.gz b/pt/tag/arraymap.html.gz new file mode 100644 index 000000000..4a9f3b508 Binary files /dev/null and b/pt/tag/arraymap.html.gz differ diff --git a/pt/tag/azure-certification.html b/pt/tag/azure-certification.html new file mode 100644 index 000000000..c52b8e672 --- /dev/null +++ b/pt/tag/azure-certification.html @@ -0,0 +1,286 @@ + + + + + + + + Azure Certification - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Azure Certification

+
+ +
+
    +
+
+
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/azure-certification.html.gz b/pt/tag/azure-certification.html.gz new file mode 100644 index 000000000..b35e51a2c Binary files /dev/null and b/pt/tag/azure-certification.html.gz differ diff --git a/pt/tag/azure-devops.html b/pt/tag/azure-devops.html new file mode 100644 index 000000000..de162b13c --- /dev/null +++ b/pt/tag/azure-devops.html @@ -0,0 +1,296 @@ + + + + + + + + Azure Devops - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/azure-devops.html.gz b/pt/tag/azure-devops.html.gz new file mode 100644 index 000000000..f9ffaf2f2 Binary files /dev/null and b/pt/tag/azure-devops.html.gz differ diff --git a/pt/tag/azure-fundamentals.html b/pt/tag/azure-fundamentals.html new file mode 100644 index 000000000..fe1deb771 --- /dev/null +++ b/pt/tag/azure-fundamentals.html @@ -0,0 +1,286 @@ + + + + + + + + Azure Fundamentals - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Azure Fundamentals

+
+ +
+
    +
+
+
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/azure-fundamentals.html.gz b/pt/tag/azure-fundamentals.html.gz new file mode 100644 index 000000000..f686e825d Binary files /dev/null and b/pt/tag/azure-fundamentals.html.gz differ diff --git a/pt/tag/azure.html b/pt/tag/azure.html new file mode 100644 index 000000000..eb18507c9 --- /dev/null +++ b/pt/tag/azure.html @@ -0,0 +1,316 @@ + + + + + + + + Azure - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/azure.html.gz b/pt/tag/azure.html.gz new file mode 100644 index 000000000..d145ec3f5 Binary files /dev/null and b/pt/tag/azure.html.gz differ diff --git a/pt/tag/c.html b/pt/tag/c.html new file mode 100644 index 000000000..80a593c6d --- /dev/null +++ b/pt/tag/c.html @@ -0,0 +1,306 @@ + + + + + + + + C# - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/c.html.gz b/pt/tag/c.html.gz new file mode 100644 index 000000000..ac270186f Binary files /dev/null and b/pt/tag/c.html.gz differ diff --git a/pt/tag/cache.html b/pt/tag/cache.html new file mode 100644 index 000000000..0b9eeff1b --- /dev/null +++ b/pt/tag/cache.html @@ -0,0 +1,296 @@ + + + + + + + + Cache - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Cache

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/cache.html.gz b/pt/tag/cache.html.gz new file mode 100644 index 000000000..ed5c2b87b Binary files /dev/null and b/pt/tag/cache.html.gz differ diff --git a/pt/tag/certification.html b/pt/tag/certification.html new file mode 100644 index 000000000..0f952618d --- /dev/null +++ b/pt/tag/certification.html @@ -0,0 +1,296 @@ + + + + + + + + Certification - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Certification

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/certification.html.gz b/pt/tag/certification.html.gz new file mode 100644 index 000000000..cd93a7151 Binary files /dev/null and b/pt/tag/certification.html.gz differ diff --git a/pt/tag/convertjsontosql.html b/pt/tag/convertjsontosql.html new file mode 100644 index 000000000..aca716fdc --- /dev/null +++ b/pt/tag/convertjsontosql.html @@ -0,0 +1,296 @@ + + + + + + + + ConvertJSONToSQL - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

ConvertJSONToSQL

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/convertjsontosql.html.gz b/pt/tag/convertjsontosql.html.gz new file mode 100644 index 000000000..2ae617275 Binary files /dev/null and b/pt/tag/convertjsontosql.html.gz differ diff --git a/pt/tag/crash.html b/pt/tag/crash.html new file mode 100644 index 000000000..d987e1c02 --- /dev/null +++ b/pt/tag/crash.html @@ -0,0 +1,296 @@ + + + + + + + + Crash - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Crash

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/crash.html.gz b/pt/tag/crash.html.gz new file mode 100644 index 000000000..92614f9ec Binary files /dev/null and b/pt/tag/crash.html.gz differ diff --git a/pt/tag/discount.html b/pt/tag/discount.html new file mode 100644 index 000000000..e43eb96ed --- /dev/null +++ b/pt/tag/discount.html @@ -0,0 +1,286 @@ + + + + + + + + Discount - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Discount

+
+ +
+
    +
+
+
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/discount.html.gz b/pt/tag/discount.html.gz new file mode 100644 index 000000000..c48af3c84 Binary files /dev/null and b/pt/tag/discount.html.gz differ diff --git a/pt/tag/disper.html b/pt/tag/disper.html new file mode 100644 index 000000000..561fe8eac --- /dev/null +++ b/pt/tag/disper.html @@ -0,0 +1,286 @@ + + + + + + + + disper - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

disper

+
+ +
+
    +
+
+
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/disper.html.gz b/pt/tag/disper.html.gz new file mode 100644 index 000000000..6e4036572 Binary files /dev/null and b/pt/tag/disper.html.gz differ diff --git a/pt/tag/django-admin.html b/pt/tag/django-admin.html new file mode 100644 index 000000000..13488a5c7 --- /dev/null +++ b/pt/tag/django-admin.html @@ -0,0 +1,296 @@ + + + + + + + + django-admin - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

django-admin

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/django-admin.html.gz b/pt/tag/django-admin.html.gz new file mode 100644 index 000000000..86290659a Binary files /dev/null and b/pt/tag/django-admin.html.gz differ diff --git a/pt/tag/django.html b/pt/tag/django.html new file mode 100644 index 000000000..c10396b04 --- /dev/null +++ b/pt/tag/django.html @@ -0,0 +1,306 @@ + + + + + + + + django - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/django.html.gz b/pt/tag/django.html.gz new file mode 100644 index 000000000..75f4ec1ed Binary files /dev/null and b/pt/tag/django.html.gz differ diff --git a/pt/tag/docker.html b/pt/tag/docker.html new file mode 100644 index 000000000..facceada0 --- /dev/null +++ b/pt/tag/docker.html @@ -0,0 +1,296 @@ + + + + + + + + Docker - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/docker.html.gz b/pt/tag/docker.html.gz new file mode 100644 index 000000000..c43fab7b6 Binary files /dev/null and b/pt/tag/docker.html.gz differ diff --git a/pt/tag/dotnet-core.html b/pt/tag/dotnet-core.html new file mode 100644 index 000000000..34a0478d3 --- /dev/null +++ b/pt/tag/dotnet-core.html @@ -0,0 +1,316 @@ + + + + + + + + DotNet Core - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/dotnet-core.html.gz b/pt/tag/dotnet-core.html.gz new file mode 100644 index 000000000..9fb07bb6e Binary files /dev/null and b/pt/tag/dotnet-core.html.gz differ diff --git a/pt/tag/dotnet.html b/pt/tag/dotnet.html new file mode 100644 index 000000000..6d507fa2a --- /dev/null +++ b/pt/tag/dotnet.html @@ -0,0 +1,316 @@ + + + + + + + + DotNet - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/dotnet.html.gz b/pt/tag/dotnet.html.gz new file mode 100644 index 000000000..cb5b00d5d Binary files /dev/null and b/pt/tag/dotnet.html.gz differ diff --git a/pt/tag/ef-core.html b/pt/tag/ef-core.html new file mode 100644 index 000000000..664543c4c --- /dev/null +++ b/pt/tag/ef-core.html @@ -0,0 +1,296 @@ + + + + + + + + EF Core - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/ef-core.html.gz b/pt/tag/ef-core.html.gz new file mode 100644 index 000000000..57d085efa Binary files /dev/null and b/pt/tag/ef-core.html.gz differ diff --git a/pt/tag/entity-framework.html b/pt/tag/entity-framework.html new file mode 100644 index 000000000..5ebaaf830 --- /dev/null +++ b/pt/tag/entity-framework.html @@ -0,0 +1,296 @@ + + + + + + + + Entity Framework - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/entity-framework.html.gz b/pt/tag/entity-framework.html.gz new file mode 100644 index 000000000..cc668e0f3 Binary files /dev/null and b/pt/tag/entity-framework.html.gz differ diff --git a/pt/tag/expressjs.html b/pt/tag/expressjs.html new file mode 100644 index 000000000..0f50d9735 --- /dev/null +++ b/pt/tag/expressjs.html @@ -0,0 +1,286 @@ + + + + + + + + expressjs - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

expressjs

+
+ +
+
    +
+
+
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/expressjs.html.gz b/pt/tag/expressjs.html.gz new file mode 100644 index 000000000..9e4b7d472 Binary files /dev/null and b/pt/tag/expressjs.html.gz differ diff --git a/pt/tag/external-display.html b/pt/tag/external-display.html new file mode 100644 index 000000000..b82739ddb --- /dev/null +++ b/pt/tag/external-display.html @@ -0,0 +1,286 @@ + + + + + + + + external display - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

external display

+
+ +
+
    +
+
+
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/external-display.html.gz b/pt/tag/external-display.html.gz new file mode 100644 index 000000000..a5c608571 Binary files /dev/null and b/pt/tag/external-display.html.gz differ diff --git a/pt/tag/filesreadallbytes.html b/pt/tag/filesreadallbytes.html new file mode 100644 index 000000000..42d5b8822 --- /dev/null +++ b/pt/tag/filesreadallbytes.html @@ -0,0 +1,286 @@ + + + + + + + + Files.readAllBytes - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Files.readAllBytes

+
+ +
+
    +
+
+
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/filesreadallbytes.html.gz b/pt/tag/filesreadallbytes.html.gz new file mode 100644 index 000000000..6ddb2583d Binary files /dev/null and b/pt/tag/filesreadallbytes.html.gz differ diff --git a/pt/tag/firebase.html b/pt/tag/firebase.html new file mode 100644 index 000000000..d4983ea9f --- /dev/null +++ b/pt/tag/firebase.html @@ -0,0 +1,286 @@ + + + + + + + + firebase - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

firebase

+
+ +
+
    +
+
+
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/firebase.html.gz b/pt/tag/firebase.html.gz new file mode 100644 index 000000000..c286a614b Binary files /dev/null and b/pt/tag/firebase.html.gz differ diff --git a/pt/tag/firefoxos.html b/pt/tag/firefoxos.html new file mode 100644 index 000000000..5f0b49f0b --- /dev/null +++ b/pt/tag/firefoxos.html @@ -0,0 +1,296 @@ + + + + + + + + FirefoxOS - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

FirefoxOS

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/firefoxos.html.gz b/pt/tag/firefoxos.html.gz new file mode 100644 index 000000000..f6dcb5d2e Binary files /dev/null and b/pt/tag/firefoxos.html.gz differ diff --git a/pt/tag/flutter.html b/pt/tag/flutter.html new file mode 100644 index 000000000..566b43905 --- /dev/null +++ b/pt/tag/flutter.html @@ -0,0 +1,286 @@ + + + + + + + + flutter - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

flutter

+
+ +
+
    +
+
+
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/flutter.html.gz b/pt/tag/flutter.html.gz new file mode 100644 index 000000000..9bbe3d959 Binary files /dev/null and b/pt/tag/flutter.html.gz differ diff --git a/pt/tag/getchild-item.html b/pt/tag/getchild-item.html new file mode 100644 index 000000000..5491156e1 --- /dev/null +++ b/pt/tag/getchild-item.html @@ -0,0 +1,296 @@ + + + + + + + + GetChild-Item - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

GetChild-Item

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/getchild-item.html.gz b/pt/tag/getchild-item.html.gz new file mode 100644 index 000000000..deaa985b0 Binary files /dev/null and b/pt/tag/getchild-item.html.gz differ diff --git a/pt/tag/git.html b/pt/tag/git.html new file mode 100644 index 000000000..b6a4b1147 --- /dev/null +++ b/pt/tag/git.html @@ -0,0 +1,286 @@ + + + + + + + + git - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

git

+
+ +
+
    +
+
+
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/git.html.gz b/pt/tag/git.html.gz new file mode 100644 index 000000000..d487de172 Binary files /dev/null and b/pt/tag/git.html.gz differ diff --git a/pt/tag/grepora.html b/pt/tag/grepora.html new file mode 100644 index 000000000..95fa36c7c --- /dev/null +++ b/pt/tag/grepora.html @@ -0,0 +1,286 @@ + + + + + + + + Grepora - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Grepora

+
+ +
+
    +
+
+
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/grepora.html.gz b/pt/tag/grepora.html.gz new file mode 100644 index 000000000..0749f8d2e Binary files /dev/null and b/pt/tag/grepora.html.gz differ diff --git a/pt/tag/hooks.html b/pt/tag/hooks.html new file mode 100644 index 000000000..250f84380 --- /dev/null +++ b/pt/tag/hooks.html @@ -0,0 +1,286 @@ + + + + + + + + hooks - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

hooks

+
+ +
+
    +
+
+
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/hooks.html.gz b/pt/tag/hooks.html.gz new file mode 100644 index 000000000..0265a8dc0 Binary files /dev/null and b/pt/tag/hooks.html.gz differ diff --git a/pt/tag/html.html b/pt/tag/html.html new file mode 100644 index 000000000..92db2b656 --- /dev/null +++ b/pt/tag/html.html @@ -0,0 +1,296 @@ + + + + + + + + Html - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ + +
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/html.html.gz b/pt/tag/html.html.gz new file mode 100644 index 000000000..6bf555cef Binary files /dev/null and b/pt/tag/html.html.gz differ diff --git a/pt/tag/icmp-pinger-more-than-75.html b/pt/tag/icmp-pinger-more-than-75.html new file mode 100644 index 000000000..757075803 --- /dev/null +++ b/pt/tag/icmp-pinger-more-than-75.html @@ -0,0 +1,296 @@ + + + + + + + + icmp pinger more than 75 - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

icmp pinger more than 75

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/icmp-pinger-more-than-75.html.gz b/pt/tag/icmp-pinger-more-than-75.html.gz new file mode 100644 index 000000000..bf4352f97 Binary files /dev/null and b/pt/tag/icmp-pinger-more-than-75.html.gz differ diff --git a/pt/tag/icmp-pinger.html b/pt/tag/icmp-pinger.html new file mode 100644 index 000000000..46e2ae0b1 --- /dev/null +++ b/pt/tag/icmp-pinger.html @@ -0,0 +1,296 @@ + + + + + + + + icmp pinger - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

icmp pinger

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/icmp-pinger.html.gz b/pt/tag/icmp-pinger.html.gz new file mode 100644 index 000000000..9041f0e83 Binary files /dev/null and b/pt/tag/icmp-pinger.html.gz differ diff --git a/pt/tag/imagemin-pngquant.html b/pt/tag/imagemin-pngquant.html new file mode 100644 index 000000000..2abeee7a0 --- /dev/null +++ b/pt/tag/imagemin-pngquant.html @@ -0,0 +1,286 @@ + + + + + + + + imagemin-pngquant - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

imagemin-pngquant

+
+ +
+
    +
+
+
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/imagemin-pngquant.html.gz b/pt/tag/imagemin-pngquant.html.gz new file mode 100644 index 000000000..2cd6061bd Binary files /dev/null and b/pt/tag/imagemin-pngquant.html.gz differ diff --git a/pt/tag/imagemin.html b/pt/tag/imagemin.html new file mode 100644 index 000000000..05ea719f9 --- /dev/null +++ b/pt/tag/imagemin.html @@ -0,0 +1,286 @@ + + + + + + + + imagemin - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

imagemin

+
+ +
+
    +
+
+
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/imagemin.html.gz b/pt/tag/imagemin.html.gz new file mode 100644 index 000000000..45f4a0722 Binary files /dev/null and b/pt/tag/imagemin.html.gz differ diff --git a/pt/tag/java.html b/pt/tag/java.html new file mode 100644 index 000000000..43646182e --- /dev/null +++ b/pt/tag/java.html @@ -0,0 +1,296 @@ + + + + + + + + Java - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/java.html.gz b/pt/tag/java.html.gz new file mode 100644 index 000000000..3c773cbb6 Binary files /dev/null and b/pt/tag/java.html.gz differ diff --git a/pt/tag/javanetsocketexception.html b/pt/tag/javanetsocketexception.html new file mode 100644 index 000000000..8f93d2128 --- /dev/null +++ b/pt/tag/javanetsocketexception.html @@ -0,0 +1,296 @@ + + + + + + + + java.net.SocketException - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/javanetsocketexception.html.gz b/pt/tag/javanetsocketexception.html.gz new file mode 100644 index 000000000..fa20e5832 Binary files /dev/null and b/pt/tag/javanetsocketexception.html.gz differ diff --git a/pt/tag/linux.html b/pt/tag/linux.html new file mode 100644 index 000000000..d34438ebf --- /dev/null +++ b/pt/tag/linux.html @@ -0,0 +1,286 @@ + + + + + + + + Linux - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Linux

+
+ +
+
    +
+
+
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/linux.html.gz b/pt/tag/linux.html.gz new file mode 100644 index 000000000..7f8e827bf Binary files /dev/null and b/pt/tag/linux.html.gz differ diff --git a/pt/tag/low-memory.html b/pt/tag/low-memory.html new file mode 100644 index 000000000..8258b1cdb --- /dev/null +++ b/pt/tag/low-memory.html @@ -0,0 +1,296 @@ + + + + + + + + Low memory - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Low memory

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/low-memory.html.gz b/pt/tag/low-memory.html.gz new file mode 100644 index 000000000..3c055beea Binary files /dev/null and b/pt/tag/low-memory.html.gz differ diff --git a/pt/tag/microservices.html b/pt/tag/microservices.html new file mode 100644 index 000000000..aa0ba0bae --- /dev/null +++ b/pt/tag/microservices.html @@ -0,0 +1,286 @@ + + + + + + + + microservices - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

microservices

+
+ +
+
    +
+
+
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/microservices.html.gz b/pt/tag/microservices.html.gz new file mode 100644 index 000000000..4677786b2 Binary files /dev/null and b/pt/tag/microservices.html.gz differ diff --git a/pt/tag/microsoft.html b/pt/tag/microsoft.html new file mode 100644 index 000000000..dc0f4214e --- /dev/null +++ b/pt/tag/microsoft.html @@ -0,0 +1,296 @@ + + + + + + + + Microsoft - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Microsoft

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/microsoft.html.gz b/pt/tag/microsoft.html.gz new file mode 100644 index 000000000..68b250866 Binary files /dev/null and b/pt/tag/microsoft.html.gz differ diff --git a/pt/tag/monitor-website.html b/pt/tag/monitor-website.html new file mode 100644 index 000000000..c1de8af12 --- /dev/null +++ b/pt/tag/monitor-website.html @@ -0,0 +1,296 @@ + + + + + + + + Monitor Website - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/monitor-website.html.gz b/pt/tag/monitor-website.html.gz new file mode 100644 index 000000000..53a4e9180 Binary files /dev/null and b/pt/tag/monitor-website.html.gz differ diff --git a/pt/tag/mysql-dual-password.html b/pt/tag/mysql-dual-password.html new file mode 100644 index 000000000..eff2bac1b --- /dev/null +++ b/pt/tag/mysql-dual-password.html @@ -0,0 +1,296 @@ + + + + + + + + MySQL Dual Password - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/mysql-dual-password.html.gz b/pt/tag/mysql-dual-password.html.gz new file mode 100644 index 000000000..041136699 Binary files /dev/null and b/pt/tag/mysql-dual-password.html.gz differ diff --git a/pt/tag/mysql-replication.html b/pt/tag/mysql-replication.html new file mode 100644 index 000000000..42e0c2a11 --- /dev/null +++ b/pt/tag/mysql-replication.html @@ -0,0 +1,296 @@ + + + + + + + + MySQL Replication - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+ +
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/mysql-replication.html.gz b/pt/tag/mysql-replication.html.gz new file mode 100644 index 000000000..56009bcd0 Binary files /dev/null and b/pt/tag/mysql-replication.html.gz differ diff --git a/pt/tag/mysql-restart.html b/pt/tag/mysql-restart.html new file mode 100644 index 000000000..30865cdbf --- /dev/null +++ b/pt/tag/mysql-restart.html @@ -0,0 +1,296 @@ + + + + + + + + MySQL Restart - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

MySQL Restart

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/mysql-restart.html.gz b/pt/tag/mysql-restart.html.gz new file mode 100644 index 000000000..60686c734 Binary files /dev/null and b/pt/tag/mysql-restart.html.gz differ diff --git a/pt/tag/mysql.html b/pt/tag/mysql.html new file mode 100644 index 000000000..1dadbd90a --- /dev/null +++ b/pt/tag/mysql.html @@ -0,0 +1,316 @@ + + + + + + + + MySQL - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/mysql.html.gz b/pt/tag/mysql.html.gz new file mode 100644 index 000000000..30a706a94 Binary files /dev/null and b/pt/tag/mysql.html.gz differ diff --git a/pt/tag/net.html b/pt/tag/net.html new file mode 100644 index 000000000..b3292565c --- /dev/null +++ b/pt/tag/net.html @@ -0,0 +1,296 @@ + + + + + + + + .net - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

.net

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/net.html.gz b/pt/tag/net.html.gz new file mode 100644 index 000000000..1e44a739b Binary files /dev/null and b/pt/tag/net.html.gz differ diff --git a/pt/tag/noclassdeffound.html b/pt/tag/noclassdeffound.html new file mode 100644 index 000000000..f4e03b1fe --- /dev/null +++ b/pt/tag/noclassdeffound.html @@ -0,0 +1,286 @@ + + + + + + + + NoClassDefFound - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

NoClassDefFound

+
+ +
+
    +
+
+
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/noclassdeffound.html.gz b/pt/tag/noclassdeffound.html.gz new file mode 100644 index 000000000..57903cffb Binary files /dev/null and b/pt/tag/noclassdeffound.html.gz differ diff --git a/pt/tag/node-js.html b/pt/tag/node-js.html new file mode 100644 index 000000000..7f9fe7c59 --- /dev/null +++ b/pt/tag/node-js.html @@ -0,0 +1,286 @@ + + + + + + + + node js - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

node js

+
+ +
+
    +
+
+
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/node-js.html.gz b/pt/tag/node-js.html.gz new file mode 100644 index 000000000..4e935efea Binary files /dev/null and b/pt/tag/node-js.html.gz differ diff --git a/pt/tag/nodejs.html b/pt/tag/nodejs.html new file mode 100644 index 000000000..e0b898de0 --- /dev/null +++ b/pt/tag/nodejs.html @@ -0,0 +1,286 @@ + + + + + + + + nodejs - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

nodejs

+
+ +
+
    +
+
+
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/nodejs.html.gz b/pt/tag/nodejs.html.gz new file mode 100644 index 000000000..91c0a1218 Binary files /dev/null and b/pt/tag/nodejs.html.gz differ diff --git a/pt/tag/out-of-memory.html b/pt/tag/out-of-memory.html new file mode 100644 index 000000000..2037a1a9f --- /dev/null +++ b/pt/tag/out-of-memory.html @@ -0,0 +1,296 @@ + + + + + + + + Out of memory - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Out of memory

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/out-of-memory.html.gz b/pt/tag/out-of-memory.html.gz new file mode 100644 index 000000000..20db9ed70 Binary files /dev/null and b/pt/tag/out-of-memory.html.gz differ diff --git a/pt/tag/outofmemory.html b/pt/tag/outofmemory.html new file mode 100644 index 000000000..1e5611a08 --- /dev/null +++ b/pt/tag/outofmemory.html @@ -0,0 +1,286 @@ + + + + + + + + outOfMemory - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

outOfMemory

+
+ +
+
    +
+
+
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/outofmemory.html.gz b/pt/tag/outofmemory.html.gz new file mode 100644 index 000000000..10bd99c4f Binary files /dev/null and b/pt/tag/outofmemory.html.gz differ diff --git a/pt/tag/parcel.html b/pt/tag/parcel.html new file mode 100644 index 000000000..56f9e5a0e --- /dev/null +++ b/pt/tag/parcel.html @@ -0,0 +1,286 @@ + + + + + + + + parcel - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

parcel

+
+ +
+
    +
+
+
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/parcel.html.gz b/pt/tag/parcel.html.gz new file mode 100644 index 000000000..d1423534a Binary files /dev/null and b/pt/tag/parcel.html.gz differ diff --git a/pt/tag/poller-proccess.html b/pt/tag/poller-proccess.html new file mode 100644 index 000000000..354d88b74 --- /dev/null +++ b/pt/tag/poller-proccess.html @@ -0,0 +1,296 @@ + + + + + + + + Poller proccess - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Poller proccess

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/poller-proccess.html.gz b/pt/tag/poller-proccess.html.gz new file mode 100644 index 000000000..35eebbecf Binary files /dev/null and b/pt/tag/poller-proccess.html.gz differ diff --git a/pt/tag/powershell-mail.html b/pt/tag/powershell-mail.html new file mode 100644 index 000000000..73eaaa9ac --- /dev/null +++ b/pt/tag/powershell-mail.html @@ -0,0 +1,296 @@ + + + + + + + + Powershell mail - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+ +
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/powershell-mail.html.gz b/pt/tag/powershell-mail.html.gz new file mode 100644 index 000000000..27fe21854 Binary files /dev/null and b/pt/tag/powershell-mail.html.gz differ diff --git a/pt/tag/powershell-monitoring.html b/pt/tag/powershell-monitoring.html new file mode 100644 index 000000000..aa92997ca --- /dev/null +++ b/pt/tag/powershell-monitoring.html @@ -0,0 +1,296 @@ + + + + + + + + Powershell monitoring - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Powershell monitoring

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/powershell-monitoring.html.gz b/pt/tag/powershell-monitoring.html.gz new file mode 100644 index 000000000..f5560963c Binary files /dev/null and b/pt/tag/powershell-monitoring.html.gz differ diff --git a/pt/tag/powershell.html b/pt/tag/powershell.html new file mode 100644 index 000000000..61d6c33e3 --- /dev/null +++ b/pt/tag/powershell.html @@ -0,0 +1,306 @@ + + + + + + + + PowerShell - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/powershell.html.gz b/pt/tag/powershell.html.gz new file mode 100644 index 000000000..ec1241a64 Binary files /dev/null and b/pt/tag/powershell.html.gz differ diff --git a/pt/tag/pre-commit.html b/pt/tag/pre-commit.html new file mode 100644 index 000000000..93783b8b3 --- /dev/null +++ b/pt/tag/pre-commit.html @@ -0,0 +1,286 @@ + + + + + + + + pre-commit - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

pre-commit

+
+ +
+
    +
+
+
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/pre-commit.html.gz b/pt/tag/pre-commit.html.gz new file mode 100644 index 000000000..28afe2ea5 Binary files /dev/null and b/pt/tag/pre-commit.html.gz differ diff --git a/pt/tag/protocol-family-unavailable.html b/pt/tag/protocol-family-unavailable.html new file mode 100644 index 000000000..f0e3466fb --- /dev/null +++ b/pt/tag/protocol-family-unavailable.html @@ -0,0 +1,296 @@ + + + + + + + + Protocol family unavailable - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/protocol-family-unavailable.html.gz b/pt/tag/protocol-family-unavailable.html.gz new file mode 100644 index 000000000..1dd6da388 Binary files /dev/null and b/pt/tag/protocol-family-unavailable.html.gz differ diff --git a/pt/tag/python.html b/pt/tag/python.html new file mode 100644 index 000000000..39297102e --- /dev/null +++ b/pt/tag/python.html @@ -0,0 +1,306 @@ + + + + + + + + python - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/python.html.gz b/pt/tag/python.html.gz new file mode 100644 index 000000000..abf06fdb6 Binary files /dev/null and b/pt/tag/python.html.gz differ diff --git a/pt/tag/rabbitmq.html b/pt/tag/rabbitmq.html new file mode 100644 index 000000000..e1f9dc0ff --- /dev/null +++ b/pt/tag/rabbitmq.html @@ -0,0 +1,286 @@ + + + + + + + + rabbitmq - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

rabbitmq

+
+ +
+
    +
+
+
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/rabbitmq.html.gz b/pt/tag/rabbitmq.html.gz new file mode 100644 index 000000000..70676bafa Binary files /dev/null and b/pt/tag/rabbitmq.html.gz differ diff --git a/pt/tag/random.html b/pt/tag/random.html new file mode 100644 index 000000000..b3454574f --- /dev/null +++ b/pt/tag/random.html @@ -0,0 +1,286 @@ + + + + + + + + Random - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Random

+
+ +
+
    +
+
+
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/random.html.gz b/pt/tag/random.html.gz new file mode 100644 index 000000000..5c7a88eeb Binary files /dev/null and b/pt/tag/random.html.gz differ diff --git a/pt/tag/raspberry.html b/pt/tag/raspberry.html new file mode 100644 index 000000000..b4589b568 --- /dev/null +++ b/pt/tag/raspberry.html @@ -0,0 +1,296 @@ + + + + + + + + raspberry - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

raspberry

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/raspberry.html.gz b/pt/tag/raspberry.html.gz new file mode 100644 index 000000000..03bc957c5 Binary files /dev/null and b/pt/tag/raspberry.html.gz differ diff --git a/pt/tag/react.html b/pt/tag/react.html new file mode 100644 index 000000000..f6bacbbe5 --- /dev/null +++ b/pt/tag/react.html @@ -0,0 +1,286 @@ + + + + + + + + react - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

react

+
+ +
+
    +
+
+
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/react.html.gz b/pt/tag/react.html.gz new file mode 100644 index 000000000..a9c260850 Binary files /dev/null and b/pt/tag/react.html.gz differ diff --git a/pt/tag/remove-item.html b/pt/tag/remove-item.html new file mode 100644 index 000000000..30b8f929d --- /dev/null +++ b/pt/tag/remove-item.html @@ -0,0 +1,296 @@ + + + + + + + + Remove-Item - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Remove-Item

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/remove-item.html.gz b/pt/tag/remove-item.html.gz new file mode 100644 index 000000000..a082be542 Binary files /dev/null and b/pt/tag/remove-item.html.gz differ diff --git a/pt/tag/removendo-underline.html b/pt/tag/removendo-underline.html new file mode 100644 index 000000000..006da7545 --- /dev/null +++ b/pt/tag/removendo-underline.html @@ -0,0 +1,296 @@ + + + + + + + + removendo underline - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

removendo underline

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/removendo-underline.html.gz b/pt/tag/removendo-underline.html.gz new file mode 100644 index 000000000..e899626fd Binary files /dev/null and b/pt/tag/removendo-underline.html.gz differ diff --git a/pt/tag/resource-governor.html b/pt/tag/resource-governor.html new file mode 100644 index 000000000..552e4f050 --- /dev/null +++ b/pt/tag/resource-governor.html @@ -0,0 +1,286 @@ + + + + + + + + Resource Governor - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Resource Governor

+
+ +
+
    +
+
+
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/resource-governor.html.gz b/pt/tag/resource-governor.html.gz new file mode 100644 index 000000000..f75fb286c Binary files /dev/null and b/pt/tag/resource-governor.html.gz differ diff --git a/pt/tag/script.html b/pt/tag/script.html new file mode 100644 index 000000000..87f025000 --- /dev/null +++ b/pt/tag/script.html @@ -0,0 +1,296 @@ + + + + + + + + Script - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Script

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/script.html.gz b/pt/tag/script.html.gz new file mode 100644 index 000000000..092e6ade3 Binary files /dev/null and b/pt/tag/script.html.gz differ diff --git a/pt/tag/shell.html b/pt/tag/shell.html new file mode 100644 index 000000000..a6c13f218 --- /dev/null +++ b/pt/tag/shell.html @@ -0,0 +1,326 @@ + + + + + + + + Shell - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/shell.html.gz b/pt/tag/shell.html.gz new file mode 100644 index 000000000..4431ca670 Binary files /dev/null and b/pt/tag/shell.html.gz differ diff --git a/pt/tag/specify-columns.html b/pt/tag/specify-columns.html new file mode 100644 index 000000000..69d98509f --- /dev/null +++ b/pt/tag/specify-columns.html @@ -0,0 +1,296 @@ + + + + + + + + Specify columns - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/specify-columns.html.gz b/pt/tag/specify-columns.html.gz new file mode 100644 index 000000000..f7048aaba Binary files /dev/null and b/pt/tag/specify-columns.html.gz differ diff --git a/pt/tag/sqlserver.html b/pt/tag/sqlserver.html new file mode 100644 index 000000000..e2ba63803 --- /dev/null +++ b/pt/tag/sqlserver.html @@ -0,0 +1,306 @@ + + + + + + + + SQLServer - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/sqlserver.html.gz b/pt/tag/sqlserver.html.gz new file mode 100644 index 000000000..675e5560f Binary files /dev/null and b/pt/tag/sqlserver.html.gz differ diff --git a/pt/tag/stop-proccess.html b/pt/tag/stop-proccess.html new file mode 100644 index 000000000..18e2925cb --- /dev/null +++ b/pt/tag/stop-proccess.html @@ -0,0 +1,296 @@ + + + + + + + + Stop-Proccess - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Stop-Proccess

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/stop-proccess.html.gz b/pt/tag/stop-proccess.html.gz new file mode 100644 index 000000000..9ba4d90da Binary files /dev/null and b/pt/tag/stop-proccess.html.gz differ diff --git a/pt/tag/the-database-principal-owns-a-schema.html b/pt/tag/the-database-principal-owns-a-schema.html new file mode 100644 index 000000000..b51d08ab3 --- /dev/null +++ b/pt/tag/the-database-principal-owns-a-schema.html @@ -0,0 +1,296 @@ + + + + + + + + The database principal owns a schema - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

The database principal owns a schema

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/the-database-principal-owns-a-schema.html.gz b/pt/tag/the-database-principal-owns-a-schema.html.gz new file mode 100644 index 000000000..847097aae Binary files /dev/null and b/pt/tag/the-database-principal-owns-a-schema.html.gz differ diff --git a/pt/tag/time-schedule-blocking.html b/pt/tag/time-schedule-blocking.html new file mode 100644 index 000000000..d6beece96 --- /dev/null +++ b/pt/tag/time-schedule-blocking.html @@ -0,0 +1,296 @@ + + + + + + + + Time Schedule blocking - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/time-schedule-blocking.html.gz b/pt/tag/time-schedule-blocking.html.gz new file mode 100644 index 000000000..1a13d3811 Binary files /dev/null and b/pt/tag/time-schedule-blocking.html.gz differ diff --git a/pt/tag/tools.html b/pt/tag/tools.html new file mode 100644 index 000000000..34fa1efd9 --- /dev/null +++ b/pt/tag/tools.html @@ -0,0 +1,296 @@ + + + + + + + + Tools - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Tools

+
+ +
+ +
+
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/tools.html.gz b/pt/tag/tools.html.gz new file mode 100644 index 000000000..80691965f Binary files /dev/null and b/pt/tag/tools.html.gz differ diff --git a/pt/tag/user.html b/pt/tag/user.html new file mode 100644 index 000000000..cd7a693f6 --- /dev/null +++ b/pt/tag/user.html @@ -0,0 +1,306 @@ + + + + + + + + User - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/user.html.gz b/pt/tag/user.html.gz new file mode 100644 index 000000000..686f12fb6 Binary files /dev/null and b/pt/tag/user.html.gz differ diff --git a/pt/tag/wildfly.html b/pt/tag/wildfly.html new file mode 100644 index 000000000..6b5ca6dd2 --- /dev/null +++ b/pt/tag/wildfly.html @@ -0,0 +1,296 @@ + + + + + + + + WildFly - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/wildfly.html.gz b/pt/tag/wildfly.html.gz new file mode 100644 index 000000000..dbc306325 Binary files /dev/null and b/pt/tag/wildfly.html.gz differ diff --git a/pt/tag/yeoman.html b/pt/tag/yeoman.html new file mode 100644 index 000000000..5c05791fb --- /dev/null +++ b/pt/tag/yeoman.html @@ -0,0 +1,296 @@ + + + + + + + + Yeoman - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+ +
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/yeoman.html.gz b/pt/tag/yeoman.html.gz new file mode 100644 index 000000000..edbce716a Binary files /dev/null and b/pt/tag/yeoman.html.gz differ diff --git a/pt/tag/zabbix-poller.html b/pt/tag/zabbix-poller.html new file mode 100644 index 000000000..734733baf --- /dev/null +++ b/pt/tag/zabbix-poller.html @@ -0,0 +1,296 @@ + + + + + + + + Zabbix Poller - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Zabbix Poller

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/zabbix-poller.html.gz b/pt/tag/zabbix-poller.html.gz new file mode 100644 index 000000000..8861086a3 Binary files /dev/null and b/pt/tag/zabbix-poller.html.gz differ diff --git a/pt/tag/zabbix-server.html b/pt/tag/zabbix-server.html new file mode 100644 index 000000000..55ae92406 --- /dev/null +++ b/pt/tag/zabbix-server.html @@ -0,0 +1,296 @@ + + + + + + + + Zabbix Server - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Zabbix Server

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/zabbix-server.html.gz b/pt/tag/zabbix-server.html.gz new file mode 100644 index 000000000..4828e03cd Binary files /dev/null and b/pt/tag/zabbix-server.html.gz differ diff --git a/pt/tag/zabbix.html b/pt/tag/zabbix.html new file mode 100644 index 000000000..ebeafc28e --- /dev/null +++ b/pt/tag/zabbix.html @@ -0,0 +1,326 @@ + + + + + + + + Zabbix - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tag/zabbix.html.gz b/pt/tag/zabbix.html.gz new file mode 100644 index 000000000..f59e436aa Binary files /dev/null and b/pt/tag/zabbix.html.gz differ diff --git a/pt/tags.html b/pt/tags.html new file mode 100644 index 000000000..9018a2b80 --- /dev/null +++ b/pt/tags.html @@ -0,0 +1,355 @@ + + + + + + + + Sipmann - Tags + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/tags.html.gz b/pt/tags.html.gz new file mode 100644 index 000000000..7a026ea08 Binary files /dev/null and b/pt/tags.html.gz differ diff --git a/pt/the-power-of-powershell.html b/pt/the-power-of-powershell.html new file mode 100644 index 000000000..25d5b0b97 --- /dev/null +++ b/pt/the-power-of-powershell.html @@ -0,0 +1,567 @@ + + + + + + + + O poder do PowerShell - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

O poder do PowerShell

+
+ +
+
+ +
+

Como um usuário linux por muito tempo, eu automatizei algumas tarefas com scripts bash e fiquei longe do PowerShell... Voltei a utilizar Windows alguns anos atrás e ainda assim, não dei uma chance ao PS. Mas porque não? Eu fiz alguns scripts para automatizar algumas tarefas em um servidor Protheus.

+

Eu acabei achando os scripts PS de fácil leitura e entendimento. Abaixo, nós temos um script para remover arquivos filtrando pela sua extensão (ou sem extensão alguma no caso do script em questão).

+
Get-ChildItem "C:\TOTVS\protheus_data\system" -File -Filter *. | Move-Item -Force -Destination { 
+    <# Diretório ao qual os arquivos vão ser movidos. Você pode utilizar formatos de data para nomear os diretórios #>
+    <# LastWriteTime é a propriedade do arquivo corrent #>
+    $dir = "C:\bad_files\{0:yyyy\\MM\\dd}" -f $_.LastWriteTime
+    $null = mkdir $dir -Force 
+    "$dir\$($_.Name)"
+}
+
+ +

Você já precisou remover arquivos baseado no conteúdo de outro arquivo? Abaixo um script onde eu leio um arquivo que contem os nomes de arquivos que eu desejo remover.

+
foreach($line in Get-Content .\Desktop\bad_files.txt) {
+    if (Test-Path('\\x.y.z.a\c$\TOTVS\protheus_data\xmls\'+$line+'.xml')) {
+        Remove-Item('\\x.y.z.a\c$\TOTVS\protheus_data\xmls\'+$line+'.xml')
+    } else {
+        echo $line + ' - File not found'
+    }
+}
+
+ +

E um script bonus para parar e iniciar serviços (se você gerencia um servidor Protheus, você sabe o porque eu faço isto).

+
$servicesNames = 'app_main',
+    'app_worker1',
+    'app_worker2',
+    'app_worker3',
+    'app_worker4',
+    'app_worker5'
+
+Write-host "Parando Serviços"
+Write-host "--------------------------"
+
+foreach ($srv in $servicesNames) {
+    Write-host "Parando: " + $srv
+    $SrvPID = (get-wmiobject win32_service | where { $_.name -eq $srv}).processID
+    Write-host "PID: " + $SrvPID
+
+    <# Força a parada caso o serviço esteja travado #>
+    Stop-Process $ServicePID -Force
+    Write-host "PDI " + $SrvPID + " parado"
+}
+
+
+Write-host "Inicializando Serviços"
+Write-host "--------------------------"
+
+foreach ($srv in $servicesNames) {
+    Write-host "Inicializando: " + $srv
+    Start-Service $srv
+}
+
+ +

Você tem algum script de automação? Compartilhe conosco :)

+
+ + +
+
+

Traduções:

+ +
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/the-power-of-powershell.html.gz b/pt/the-power-of-powershell.html.gz new file mode 100644 index 000000000..c7fd42f59 Binary files /dev/null and b/pt/the-power-of-powershell.html.gz differ diff --git a/pt/top_level_statement_csharp_9.html b/pt/top_level_statement_csharp_9.html new file mode 100644 index 000000000..fdb14ddff --- /dev/null +++ b/pt/top_level_statement_csharp_9.html @@ -0,0 +1,513 @@ + + + + + + + + Top Level Statement no C# 9 - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Top Level Statement no C# 9

+
+ +
+
+ +
+

Olá pessoal, venho hoje falar sobre uma novidade que estará disponível na versão 9 do C#. Toda vez que você deseja criar um novo projeto, você sempre tem o mesmo arquivo Main, com a mesma estrutura. Na próxima versão do C# (versão 9), nós teremos uma nova funcionalidade chamada Top Level Statement. Com isto, poderemos programar a nossa aplicação sem toda aquela estrutura de namespace/class/public void static main. Veja o código abaixo.

+
using System;
+
+Console.WriteLine("Hello World!");
+
+ +

Parece muito simples, não é? Com isto, você pode brincar com seu código e até mesmo programar uma pequena WEB API. Para começar a brincar com estas novas features, primeiramente faça o download do preview do .net 5 SDK e modifique o seu arquivo .csproj para apontar o framework para .net5.0 e a versão de preview da linguagem. Abaixo como uma aplicação de console deve ficar.

+
<Project Sdk="Microsoft.NET.Sdk">
+  <PropertyGroup>
+    <OutputType>Exe</OutputType>
+    <TargetFramework>net5.0</TargetFramework>
+    <LangVersion>preview</LangVersion>
+  </PropertyGroup>
+</Project>
+
+ +

E assim você está pronto para brincar com as novas funcionalidades que estão disponíveis na versão preview. Vamos programar uma aplicação simples que faz uma requisição na API da NASA e printe a Imagem do Dia no console. Não é nenhum código mirabolante, é simplesmente para exemplificar o quão simples uma simples chamada de API pode ser. Feito isto, porque não salvar a imagem como um arquivo? Ou então enviar essa imagem via telegram?

+
using System;
+using System.Net.Http;
+using System.Text.Json;
+
+var API = "https://api.nasa.gov/planetary/apod?hd=true&api_key=DEMO_KEY";
+var cli = new HttpClient();
+
+var response = await cli.GetAsync(API);
+var data = JsonSerializer.Deserialize<NasaApi>(await response.Content.ReadAsStringAsync());
+
+Console.WriteLine(data.Url);
+
+ +

Por hoje é isso. Fique de olho nas novas features que o C# 9 vai nos trazer. Já temos várias disponíveis hoje para testar, esta é apenas uma delas.

+
+ + +
+
+

Traduções:

+ +
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/top_level_statement_csharp_9.html.gz b/pt/top_level_statement_csharp_9.html.gz new file mode 100644 index 000000000..84e593d7c Binary files /dev/null and b/pt/top_level_statement_csharp_9.html.gz differ diff --git a/pt/zabbix-icmp-pinger-processes-more-than-75.html b/pt/zabbix-icmp-pinger-processes-more-than-75.html new file mode 100644 index 000000000..34ac9f89a --- /dev/null +++ b/pt/zabbix-icmp-pinger-processes-more-than-75.html @@ -0,0 +1,521 @@ + + + + + + + + Zabbix ICMP pinger processes more than 75% - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Zabbix ICMP pinger processes more than 75%

+
+ +
+
+ +
+

Então o seu systema de monitoramento creasceu e o seu Zabbix começou a printar "Zabbix icmp pinger processes more than 75% busy" no seu dashboard.

+

Dashboard do zabbix avisando sobre o erro

+

Tudo que você tem a fazer é abrir o seu arquivo de configuração (/etc/zabbix/zabbix_server.conf) e localizar a tag chamada StartPingers. Ela deve estar comentáda por padrão. Descomente a lina e define o seu valor para algo como 3 or 4. Deve resolver seu problema, ao menos até um próximo crescimento do seu monitoramento.

+
### Option: StartPingers
+#       Number of pre-forked instances of ICMP pingers.
+#
+# Mandatory: no
+# Range: 0-1000
+# Default:
+StartPingers=4
+

+
+ + +
+
+

Traduções:

+ +
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/zabbix-icmp-pinger-processes-more-than-75.html.gz b/pt/zabbix-icmp-pinger-processes-more-than-75.html.gz new file mode 100644 index 000000000..06ba73d5c Binary files /dev/null and b/pt/zabbix-icmp-pinger-processes-more-than-75.html.gz differ diff --git a/pt/zabbix-poller-processes-more-than-75.html b/pt/zabbix-poller-processes-more-than-75.html new file mode 100644 index 000000000..fee54662c --- /dev/null +++ b/pt/zabbix-poller-processes-more-than-75.html @@ -0,0 +1,565 @@ + + + + + + + + Zabbix poller processes more than 75% - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Zabbix poller processes more than 75%

+
+ +
+
+ +
+

Este é o terceiro post sobre configurações para o Zabbix. Todas as alterações que eu sugiro nestes posts, são baseadas em um servidor com 50+ hosts. Outro problema que pode ocorrer em seu servidor, é o poller de informações ficar sobrecarregado pela quantidade de servidores que ele precisa pegar carga de informações juntamente com os servidores que não respondem a requisição. Abaixo duas imagens onde você pode ver o log e um gráfico onde aparecem os percentuais de uso dos poller.

+

Dashboard log sobre o processo do poller

+

Gráfico mostrando o percentual de utilização de cada coletor

+

Para resolver o problema acima, vamos voltar ao arquivo de configuração zabbix_server.conf e localizar duas variáveis, StartPollers e StartPollersUnreachable. Aumente o valor delas conforme necessário. Não existe um número mágico, você deve verificar o que melhor funciona para você. Mas tenha em mente que StartPollersUnreachable é responsável por aqueles hosts que não respondem ou não são localizados e irão segurar a thread do poller por mais tempo, causando uma fila e um maior processamento/tempo de atualização.

+
### Option: StartPollers
+#       Number of pre-forked instances of pollers.
+#
+# Mandatory: no
+# Range: 0-1000
+# Default:
+StartPollers=20
+
+#...
+
+### Option: StartPollersUnreachable
+#       Number of pre-forked instances of pollers for unreachable hosts (including IPMI and Java).
+#       At least one poller for unreachable hosts must be running if regular, IPMI or Java pollers
+#       are started.
+#
+# Mandatory: no
+# Range: 0-1000
+# Default:
+StartPollersUnreachable=5
+
+ +

Depois da alteração, reinicie o serviço e espere alguns momentos e veja o seu dashboard novamente. Abaixo o efeito que a troca teve em um dos servidores que acompanho.

+

Gráfico mostrando os novos percentuais de utilização dos processos após as alterações

+
+ + +
+
+

Traduções:

+ +
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/zabbix-poller-processes-more-than-75.html.gz b/pt/zabbix-poller-processes-more-than-75.html.gz new file mode 100644 index 000000000..6e01d73f7 Binary files /dev/null and b/pt/zabbix-poller-processes-more-than-75.html.gz differ diff --git a/pt/zabbix-running-on-low-memory-mode.html b/pt/zabbix-running-on-low-memory-mode.html new file mode 100644 index 000000000..daf04e5d2 --- /dev/null +++ b/pt/zabbix-running-on-low-memory-mode.html @@ -0,0 +1,554 @@ + + + + + + + + Zabbix Running on Low Memory Mode - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Zabbix Running on Low Memory Mode

+
+ +
+
+ +
+

Olá pessoal! Trago hoje outro post sobre Zabbix. Este é sobre aumentar o cache do seu Zabbix Server. É perfeitamente comum (se você roda com as configurações padrões) receber avisos sobre Zabbix value cache running on low memory mode no seu dashboard ou arquivos de log.

+

Zabbix Dashboard alertando sobre problemas de memória +Zabbix Dashboard cache gráfico com 70% utilizado

+

Para resolver, abra o seu arquivo de configuração (zabbix_server.conf) e procure pela tag CacheSize. Descomente a linha e defina um valor maior que 8M (8M é o valor padrão). No meu caso, nós configuramos um cache de 100M. Depois da troca, reinicie o serviço para que o mesmo tome efeito.

+
### Option: CacheSize
+#       Size of configuration cache, in bytes.
+#       Shared memory size for storing host, item and trigger data.
+#
+# Mandatory: no
+# Range: 128K-64G
+# Default:
+CacheSize=100M #Descomente esta linha
+
+ +

Zabbix Dashboard resolved memory problem

+

Até breve.

+
+ + +
+
+

Traduções:

+ +
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/zabbix-running-on-low-memory-mode.html.gz b/pt/zabbix-running-on-low-memory-mode.html.gz new file mode 100644 index 000000000..3f28e22b9 Binary files /dev/null and b/pt/zabbix-running-on-low-memory-mode.html.gz differ diff --git a/pt/zabbix-server-out-of-memory-crash.html b/pt/zabbix-server-out-of-memory-crash.html new file mode 100644 index 000000000..7ce0d553e --- /dev/null +++ b/pt/zabbix-server-out-of-memory-crash.html @@ -0,0 +1,546 @@ + + + + + + + + Zabbix Server Out of Memory - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Zabbix Server Out of Memory

+
+ +
+
+ +
+

Você tem um servidor Zabbix crashando e observando o arquivo de log /var/log/zabbix/zabbix_server.log você localiza a seguinte mensagem referênciando falta de memória?

+
__mem_malloc: skipped 0 asked 24 skip_min 18446744073709551615 skip_max 0
+[file:dbconfig.c,line:94] __zbx_mem_realloc(): out of memory (requested 16 bytes)
+[file:dbconfig.c,line:94] __zbx_mem_realloc(): please increase CacheSize configuration parameter
+
+ +

Apesar da simples solução para o erro, isso acaba sendo um problema comum em servidores que tem uma certa quantidade de itens sendo monitorados (servidores, switches, firewalls, bancos, etc...). Para resolver o problema, vá até o ser arquivo zabbix_server.conf e procure pela propriedade CacheSize e sete o seu valor para uma quantidade maior. O seu valor default deve ser algo como 8M. Em clientes que tenham algo como 4 servidores, 7 firewalls/appliances, e algumas outras coisas (bancos, apps), 32M deve resolver o problema, mas você pode setar até algo como 8G (ressalto que mais memória nem sempre é melhor).

+

Até breve.

+
+ + +
+
+

Traduções:

+ +
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pt/zabbix-server-out-of-memory-crash.html.gz b/pt/zabbix-server-out-of-memory-crash.html.gz new file mode 100644 index 000000000..cd671cd5a Binary files /dev/null and b/pt/zabbix-server-out-of-memory-crash.html.gz differ diff --git a/reading-files-java-readAllBytes-outofmemory.html b/reading-files-java-readAllBytes-outofmemory.html new file mode 100644 index 000000000..af7a8b89c --- /dev/null +++ b/reading-files-java-readAllBytes-outofmemory.html @@ -0,0 +1,510 @@ + + + + + + + + Java - Files.readAllBytes throws OutOfMemory - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Java - Files.readAllBytes throws OutOfMemory

+
+ +
+
+ +
+

When you need to interact with files, there's the possibility to read all bytes from the file with Files.readAllBytes. But be aware of the kinds of files your application will deal with because the Java API files have a limit for the buffer that is defined as Integer.MAX_VALUE as you can see above or at the OpenJDK sources.

+
public static byte[] readAllBytes(Path path) throws IOException {
+    try (FileChannel fc = FileChannel.open(path)) {
+        long size = fc.size();
+        if (size > (long)Integer.MAX_VALUE)
+            throw new OutOfMemoryError("Required array size too large");
+
+        byte[] arr = new byte[(int)size];
+        ByteBuffer bb = ByteBuffer.wrap(arr);
+        while (bb.hasRemaining()) {
+            if (fc.read(bb) < 0) {
+                // truncated
+                break;
+            }
+        }
+
+        int nread = bb.position();
+        return (nread == size) ? arr : Arrays.copyOf(arr, nread);
+    }
+}
+
+

With that in mind, check if isn't better read chunks of bytes e work with that slice in exchange of loading the whole file into the memory ;). Above a simple example of how you can read chunks of bytes from the file.

+
byte[] buffer = new byte[1024];
+FileInputStream in = new FileInputStream(file);
+int rc = in.read(buffer);
+while (rc != -1)
+{
+    //crazy stuff here with buffer
+    rc = in.read(buffer);
+}
+
+

+
+ + +
+
+

Translations:

+
    +
+
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/reading-files-java-readAllBytes-outofmemory.html.gz b/reading-files-java-readAllBytes-outofmemory.html.gz new file mode 100644 index 000000000..19531966e Binary files /dev/null and b/reading-files-java-readAllBytes-outofmemory.html.gz differ diff --git a/removing-user-from-sql-server-database.html b/removing-user-from-sql-server-database.html new file mode 100644 index 000000000..9cfd7df58 --- /dev/null +++ b/removing-user-from-sql-server-database.html @@ -0,0 +1,519 @@ + + + + + + + + Removing a user from SQL Server database who owns a schema - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Removing a user from SQL Server database who owns a schema

+
+ +
Updated: 21 October 2020 +
+
+ +
+

Your customer urge you to drop a user from the MsSQL Server database, but you stuck with the following related error:

+
Error: 15138 The database principal owns a schema in the database, and cannot be dropped.
+
+ +

That means that the user owns one or more shcemas of your database. If you don't have access to the SSMS to see which schema or objects the user owns, the following SQL should do the job.

+
USE [DATABASENAME]
+GO
+
+select so.name Objeto, su.name Owner
+from sys.schemas so
+inner join sysusers su on so.principal_id = su.uid
+where su.name = 'username'
+
+select so.name Objeto, su.name Owner, so.xtype Tipo
+from sys.sysobjects so
+inner join sysusers su on so.uid = su.uid
+where su.name = 'username'
+
+ +

Once you have the objects/schemas owned by the user, you can change them with the following SQL (schema change sample):

+
USE [DATABASENAME]
+GO
+ALTER AUTHORIZATION ON SCHEMA::[db_datareader] TO [dbo] -- new owner username
+ALTER AUTHORIZATION ON SCHEMA::[db_datawriter] TO [dbo]
+GO
+
+ +

Then you're ready to drop the user DROP USER [username]

+

How to list all the schemas and it's owners?

+

Here's a script to list schemas and it's owners.

+
USE [DATABASENAME]
+GO
+SELECT
+    schema_name(schema_id) AS schemaname,
+    user_name(schm.principal_id) AS username, *
+FROM sys.schemas AS schm
+GO
+

+
+ + +
+
+

Translations:

+ +
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/removing-user-from-sql-server-database.html.gz b/removing-user-from-sql-server-database.html.gz new file mode 100644 index 000000000..60987710f Binary files /dev/null and b/removing-user-from-sql-server-database.html.gz differ diff --git a/scaffolding_react_app_with_parcel_yeoman.html b/scaffolding_react_app_with_parcel_yeoman.html new file mode 100644 index 000000000..3a9840b8f --- /dev/null +++ b/scaffolding_react_app_with_parcel_yeoman.html @@ -0,0 +1,504 @@ + + + + + + + + Scaffolding a React app with Parcel and Yeoman - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+ + +
+

Since Parcel JS arrived, I've been using it a lot as an awesome alternative for WebPack. Webpack isn't bad but IMO it's too complex for the job and parcel do the same (at least the basic) with almost zero configuration. But if you need to create many apps (like a react app) over and over again, it get's a lil boring following the basic steps.

+
npm init -y
+npm install --save react
+npm install --save react-dom
+npm install --save-dev parcel-bundler
+npm install --save-dev babel-preset-env
+npm install --save-dev babel-preset-react
+
+#create .babelrc file
+#create html, css, jsx files
+
+parcel index.html
+
+

It's not a hard job, a simple shell script do the job, but what if you need some IFs when creating the app, or even change a few things at the package.json? A shell script still does the job, but come on... There is a better way. Yeoman is here for you. I've already talked about it on another post (Portuguese post).

+

Straight to the point, I've released a Yeoman generator to get the things a lil quicker. The name is generator-parcel-react and it still lacks a few things that I will deal with soon. It's pretty simple to use it.

+
#First time only
+npm install -g yo
+npm install -g generator-parcel-react
+
+#every time you create a new app
+yo parcel-react
+
+

And that's it. Right now you can scaffold and app with React, SASS and React Router. Hope you like it and feel free to ask new features.

+

+
+ + +
+
+

Translations:

+
    +
+
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/scaffolding_react_app_with_parcel_yeoman.html.gz b/scaffolding_react_app_with_parcel_yeoman.html.gz new file mode 100644 index 000000000..57a11d0de Binary files /dev/null and b/scaffolding_react_app_with_parcel_yeoman.html.gz differ diff --git a/select_specific_fields_with_efcore.html b/select_specific_fields_with_efcore.html new file mode 100644 index 000000000..647f3a475 --- /dev/null +++ b/select_specific_fields_with_efcore.html @@ -0,0 +1,505 @@ + + + + + + + + How to set columns on select using Entity Framework - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+ + +
+

So, you use Entity Framework Core, and you usually code your selects like the following, maybe you are getting too much data.

+
var products = Products
+    .Where(p => p.UnitsInStock > 0)
+    .OrderBy(p => p.ProductName)
+    .ToList()
+
+ +

Running the query above, on my table, you'll get the following output, take a look at how many columns you are getting back from your database.

+

Screenshot with every single column

+

In my case, I only care about the Title, PublishedData, and a small description. So to get back only these fields, we have a few options. In the first one, we'll set the fields and return them as a dynamic object, the second one, is to give the .NET a class to use.

+
var products = Products
+
+    .Select(p => new {p.ProductID, p.ProductName, p.UnitsInStock, p.UnitPrice})
+    //.Select(p => new ProductDTO {p.ProductID, p.ProductName, p.UnitsInStock, p.UnitPrice})
+
+    .Where(p => p.UnitsInStock > 0)
+    .OrderBy(p => p.ProductName)
+    .ToList()
+
+ +

Screenshot with fewer columns and also fewer data size

+
+ + +
+
+

Translations:

+ +
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/select_specific_fields_with_efcore.html.gz b/select_specific_fields_with_efcore.html.gz new file mode 100644 index 000000000..1a6455360 Binary files /dev/null and b/select_specific_fields_with_efcore.html.gz differ diff --git a/sitemap.xml b/sitemap.xml new file mode 100644 index 000000000..382c4f3fa --- /dev/null +++ b/sitemap.xml @@ -0,0 +1,881 @@ + + + + +https://www.sipmann.com/ +2024-02-14T00:32:49-00:00 +daily +0.4 + + + +https://www.sipmann.com/tags.html +2024-02-14T00:32:49-00:00 +daily +0.4 + + + +https://www.sipmann.com/categories.html +2024-02-14T00:32:49-00:00 +daily +0.4 + + + +https://www.sipmann.com/authors.html +2024-02-14T00:32:49-00:00 +daily +0.4 + + + +https://www.sipmann.com/archives.html +2024-02-14T00:32:49-00:00 +daily +0.4 + + + +https://www.sipmann.com/monitoring-mysql-restarts-with-powershell.html +2020-12-21T13:30:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/mysql-dual-password-functionality.html +2020-12-09T13:40:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/apache-nifi-json-to-sql-replacing-underscore.html +2020-12-02T14:00:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/blocking-user-on-sql-server-based-on-schedule.html +2020-11-14T07:00:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/select_specific_fields_with_efcore.html +2020-10-28T19:00:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/zabbix-running-on-low-memory-mode.html +2020-10-20T19:00:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/monitoring-mysql-replication-with-powershell.html +2020-10-14T19:00:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/microsoft-against-covid.html +2020-10-03T19:00:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/the-power-of-powershell.html +2020-09-21T19:00:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/top_level_statement_csharp_9.html +2020-07-29T19:00:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/zabbix-poller-processes-more-than-75.html +2020-07-02T19:00:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/monitoring-website-heath-with-azure-functions.html +2020-06-22T19:00:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/azure-data-fundamentals-certification-80-discount.html +2020-06-09T12:30:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/zabbix-icmp-pinger-processes-more-than-75.html +2020-05-25T16:00:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/zabbix-server-out-of-memory-crash.html +2020-02-27T19:00:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/flutter_with_firebase_auth_crashing.html +2019-10-03T19:00:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/removing-user-from-sql-server-database.html +2020-10-21T18:40:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/limiting-connection-resources-sql-server.html +2019-08-12T12:00:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/using_git_hooks_easy_your_life.html +2019-07-30T20:00:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/microservices_nodejs_express_rabbitmq_part_2.html +2018-04-13T13:00:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/microservices_nodejs_express_rabbitmq_part_1.html +2018-04-04T11:25:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/connecting_to_database_through_ssh.html +2018-03-29T10:03:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/now_posting_on_grepora.html +2018-03-24T00:40:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/scaffolding_react_app_with_parcel_yeoman.html +2018-03-17T13:00:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/cloud-not-open-connection-java-mysql-hibernate.html +2018-03-09T12:35:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/socketException-protocol-family-unavailable-java-docker-wildfly.html +2018-03-04T17:40:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/linux-external-display-with-disper.html +2018-02-27T12:40:00-03:00 +monthly +0.8 + + + +https://www.sipmann.com/reading-files-java-readAllBytes-outofmemory.html +2018-02-17T13:00:00-02:00 +monthly +0.8 + + + +https://www.sipmann.com/category/azure.html +2020-10-03T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/category/flutter.html +2019-10-03T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/category/front-end.html +2018-04-13T13:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/category/java.html +2018-03-09T12:35:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/category/linux.html +2020-10-20T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/category/mysql.html +2020-12-09T13:40:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/category/net.html +2020-10-28T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/category/powershell.html +2020-12-21T13:30:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/category/random.html +2018-03-24T00:40:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/category/sql-server.html +2020-11-14T07:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/category/tools.html +2020-12-02T14:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/mysql.html +2020-12-21T13:30:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/mysql-restart.html +2020-12-21T13:30:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/powershell-monitoring.html +2020-12-21T13:30:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/mysql-dual-password.html +2020-12-09T13:40:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/apache-nifi.html +2020-12-02T14:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/convertjsontosql.html +2020-12-02T14:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/replacing-underscore.html +2020-12-02T14:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/sqlserver.html +2020-11-14T07:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/user.html +2020-11-14T07:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/time-schedule-blocking.html +2020-11-14T07:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/dotnet.html +2020-10-28T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/dotnet-core.html +2020-10-28T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/entity-framework.html +2020-10-28T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/ef-core.html +2020-10-28T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/specify-columns.html +2020-10-28T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/zabbix.html +2020-10-20T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/shell.html +2020-10-20T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/low-memory.html +2020-10-20T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/cache.html +2020-10-20T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/mysql-replication.html +2020-10-14T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/powershell.html +2020-10-14T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/powershell-mail.html +2020-10-14T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/azure.html +2020-10-03T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/certification.html +2020-10-03T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/microsoft.html +2020-10-03T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/script.html +2020-09-21T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/getchild-item.html +2020-09-21T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/remove-item.html +2020-09-21T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/stop-proccess.html +2020-09-21T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/c.html +2020-07-29T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/net.html +2020-07-29T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/zabbix-poller.html +2020-07-02T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/poller-proccess-more-than-75.html +2020-07-02T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/azure-devops.html +2020-06-22T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/monitor-website.html +2020-06-22T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/azure-fundamentals.html +2020-06-09T12:30:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/azure-certification.html +2020-06-09T12:30:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/discount.html +2020-06-09T12:30:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/icmp-pinger.html +2020-05-25T16:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/icmp-pinger-more-than-75.html +2020-05-25T16:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/zabbix-server.html +2020-05-25T16:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/out-of-memory.html +2020-02-27T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/crash.html +2020-02-27T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/flutter.html +2019-10-03T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/firebase.html +2019-10-03T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/arraymap.html +2019-10-03T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/noclassdeffound.html +2019-10-03T19:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/the-database-principal-owns-a-schema.html +2020-10-21T18:40:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/resource-governor.html +2019-08-12T12:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/git.html +2019-07-30T20:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/pre-commit.html +2019-07-30T20:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/hooks.html +2019-07-30T20:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/nodejs.html +2018-04-13T13:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/microservices.html +2018-04-13T13:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/rabbitmq.html +2018-04-13T13:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/expressjs.html +2018-04-13T13:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/imagemin.html +2018-04-13T13:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/imagemin-pngquant.html +2018-04-13T13:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/node-js.html +2018-04-13T13:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/openssh.html +2018-03-29T10:03:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/tunnel.html +2018-03-29T10:03:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/ssh-tunnel.html +2018-03-29T10:03:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/ssh.html +2018-03-29T10:03:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/through-firewall.html +2018-03-29T10:03:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/grepora.html +2018-03-24T00:40:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/random.html +2018-03-24T00:40:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/yeoman.html +2018-03-17T13:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/parcel.html +2018-03-17T13:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/react.html +2018-03-17T13:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/java.html +2018-03-09T12:35:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/hibernate.html +2018-03-09T12:35:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/wildfly.html +2018-03-04T17:40:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/docker.html +2018-03-04T17:40:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/javanetsocketexception.html +2018-03-04T17:40:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/protocol-family-unavailable.html +2018-03-04T17:40:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/linux.html +2018-02-27T12:40:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/external-display.html +2018-02-27T12:40:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/disper.html +2018-02-27T12:40:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/filesreadallbytes.html +2018-02-17T13:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/tag/outofmemory.html +2018-02-17T13:00:00-03:06 +daily +0.4 + + + +https://www.sipmann.com/author/mauricio-camargo-sipmann.html +2020-12-21T13:30:00-03:06 +daily +0.4 + + + diff --git a/sitemap.xml.gz b/sitemap.xml.gz new file mode 100644 index 000000000..d21633ac5 Binary files /dev/null and b/sitemap.xml.gz differ diff --git a/socketException-protocol-family-unavailable-java-docker-wildfly.html b/socketException-protocol-family-unavailable-java-docker-wildfly.html new file mode 100644 index 000000000..90a742408 --- /dev/null +++ b/socketException-protocol-family-unavailable-java-docker-wildfly.html @@ -0,0 +1,490 @@ + + + + + + + + Solving java.net.SocketException: Protocol family unavailable on a Java + Docker + WildFly - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+ + +
+

On the last days I've been playing with WildFly Swarm and I decided to deploy a simple app with Docker. Should work fine, at least that was what I thought. Built a container with the following Dockerfile and instead of a working web app, all that I got was the error java.net.SocketException: Protocol family unavailable.

+
FROM java:openjdk-8-jdk
+
+COPY target/issues.jar /opt/issues.jar
+
+EXPOSE 8080
+
+CMD ["java","-jar","/opt/issues.jar"]
+
+

For some reason, WildFly and Java decided to use the IPv6 network interface from Docker instead the v4, so all you have to do is tell Java to prefer IPv4 instead with the following configuration option in your pom.xml file inside your WildFly plugin.

+
<plugin>
+        <groupId>org.wildfly.swarm</groupId>
+        <artifactId>wildfly-swarm-plugin</artifactId>
+        <version>2018.2.0</version>
+
+        <!-- ADD THIS -->
+        <configuration>
+          <mainClass>org.wildfly.swarm.examples.netflix.ribbon.frontend.Main</mainClass>
+          <properties>
+                <java.net.preferIPv4Stack>true</java.net.preferIPv4Stack>
+          </properties>
+        </configuration>
+
+

Another way to solve is adding the same properties to the run command at the Dockerfile, so you choose where you'll add it. Bellow the Dockerfile solution.

+
FROM java:openjdk-8-jdk
+ENV JAVA_OPTS="-Djava.net.preferIPv4Stack=true -Djava.net.preferIPv4Addresses=true"
+
+COPY target/issues.jar /opt/issues.jar
+
+EXPOSE 8080
+
+ENTRYPOINT exec java $JAVA_OPTS -jar /opt/issues.jar
+
+

+
+ + +
+
+

Translations:

+ +
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/socketException-protocol-family-unavailable-java-docker-wildfly.html.gz b/socketException-protocol-family-unavailable-java-docker-wildfly.html.gz new file mode 100644 index 000000000..21058e1df Binary files /dev/null and b/socketException-protocol-family-unavailable-java-docker-wildfly.html.gz differ diff --git a/tag/apache-nifi.html b/tag/apache-nifi.html new file mode 100644 index 000000000..3c23a5326 --- /dev/null +++ b/tag/apache-nifi.html @@ -0,0 +1,296 @@ + + + + + + + + Apache Nifi - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Apache Nifi

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/apache-nifi.html.gz b/tag/apache-nifi.html.gz new file mode 100644 index 000000000..4f0a4d2b9 Binary files /dev/null and b/tag/apache-nifi.html.gz differ diff --git a/tag/arraymap.html b/tag/arraymap.html new file mode 100644 index 000000000..a73f07039 --- /dev/null +++ b/tag/arraymap.html @@ -0,0 +1,296 @@ + + + + + + + + ArrayMap - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

ArrayMap

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/arraymap.html.gz b/tag/arraymap.html.gz new file mode 100644 index 000000000..5494cc786 Binary files /dev/null and b/tag/arraymap.html.gz differ diff --git a/tag/azure-certification.html b/tag/azure-certification.html new file mode 100644 index 000000000..556eed63d --- /dev/null +++ b/tag/azure-certification.html @@ -0,0 +1,296 @@ + + + + + + + + Azure Certification - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Azure Certification

+
+ + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/azure-certification.html.gz b/tag/azure-certification.html.gz new file mode 100644 index 000000000..f8b2e08a6 Binary files /dev/null and b/tag/azure-certification.html.gz differ diff --git a/tag/azure-devops.html b/tag/azure-devops.html new file mode 100644 index 000000000..f5a43919e --- /dev/null +++ b/tag/azure-devops.html @@ -0,0 +1,296 @@ + + + + + + + + Azure Devops - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Azure Devops

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/azure-devops.html.gz b/tag/azure-devops.html.gz new file mode 100644 index 000000000..43bc4c97f Binary files /dev/null and b/tag/azure-devops.html.gz differ diff --git a/tag/azure-fundamentals.html b/tag/azure-fundamentals.html new file mode 100644 index 000000000..933dc9981 --- /dev/null +++ b/tag/azure-fundamentals.html @@ -0,0 +1,296 @@ + + + + + + + + Azure Fundamentals - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Azure Fundamentals

+
+ + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/azure-fundamentals.html.gz b/tag/azure-fundamentals.html.gz new file mode 100644 index 000000000..7d17b81b0 Binary files /dev/null and b/tag/azure-fundamentals.html.gz differ diff --git a/tag/azure.html b/tag/azure.html new file mode 100644 index 000000000..ffb4e190f --- /dev/null +++ b/tag/azure.html @@ -0,0 +1,326 @@ + + + + + + + + Azure - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/azure.html.gz b/tag/azure.html.gz new file mode 100644 index 000000000..8c77622b3 Binary files /dev/null and b/tag/azure.html.gz differ diff --git a/tag/c.html b/tag/c.html new file mode 100644 index 000000000..ff922d48e --- /dev/null +++ b/tag/c.html @@ -0,0 +1,306 @@ + + + + + + + + C# - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/c.html.gz b/tag/c.html.gz new file mode 100644 index 000000000..1a43ada39 Binary files /dev/null and b/tag/c.html.gz differ diff --git a/tag/cache.html b/tag/cache.html new file mode 100644 index 000000000..1545727f0 --- /dev/null +++ b/tag/cache.html @@ -0,0 +1,296 @@ + + + + + + + + Cache - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Cache

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/cache.html.gz b/tag/cache.html.gz new file mode 100644 index 000000000..00598d231 Binary files /dev/null and b/tag/cache.html.gz differ diff --git a/tag/certification.html b/tag/certification.html new file mode 100644 index 000000000..c99c8bc2c --- /dev/null +++ b/tag/certification.html @@ -0,0 +1,296 @@ + + + + + + + + Certification - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Certification

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/certification.html.gz b/tag/certification.html.gz new file mode 100644 index 000000000..a507f8aa9 Binary files /dev/null and b/tag/certification.html.gz differ diff --git a/tag/convertjsontosql.html b/tag/convertjsontosql.html new file mode 100644 index 000000000..735521f6f --- /dev/null +++ b/tag/convertjsontosql.html @@ -0,0 +1,296 @@ + + + + + + + + ConvertJSONToSQL - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

ConvertJSONToSQL

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/convertjsontosql.html.gz b/tag/convertjsontosql.html.gz new file mode 100644 index 000000000..051398c98 Binary files /dev/null and b/tag/convertjsontosql.html.gz differ diff --git a/tag/crash.html b/tag/crash.html new file mode 100644 index 000000000..bc1597aa6 --- /dev/null +++ b/tag/crash.html @@ -0,0 +1,296 @@ + + + + + + + + Crash - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Crash

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/crash.html.gz b/tag/crash.html.gz new file mode 100644 index 000000000..aa523a3f6 Binary files /dev/null and b/tag/crash.html.gz differ diff --git a/tag/discount.html b/tag/discount.html new file mode 100644 index 000000000..818d10807 --- /dev/null +++ b/tag/discount.html @@ -0,0 +1,296 @@ + + + + + + + + Discount - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/discount.html.gz b/tag/discount.html.gz new file mode 100644 index 000000000..9216673b0 Binary files /dev/null and b/tag/discount.html.gz differ diff --git a/tag/disper.html b/tag/disper.html new file mode 100644 index 000000000..66fdea10a --- /dev/null +++ b/tag/disper.html @@ -0,0 +1,296 @@ + + + + + + + + disper - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+ +
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/disper.html.gz b/tag/disper.html.gz new file mode 100644 index 000000000..dbbc9a908 Binary files /dev/null and b/tag/disper.html.gz differ diff --git a/tag/docker.html b/tag/docker.html new file mode 100644 index 000000000..98d2dd892 --- /dev/null +++ b/tag/docker.html @@ -0,0 +1,296 @@ + + + + + + + + Docker - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/docker.html.gz b/tag/docker.html.gz new file mode 100644 index 000000000..8b892942e Binary files /dev/null and b/tag/docker.html.gz differ diff --git a/tag/dotnet-core.html b/tag/dotnet-core.html new file mode 100644 index 000000000..aa52b1766 --- /dev/null +++ b/tag/dotnet-core.html @@ -0,0 +1,316 @@ + + + + + + + + DotNet Core - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/dotnet-core.html.gz b/tag/dotnet-core.html.gz new file mode 100644 index 000000000..8b930ba0a Binary files /dev/null and b/tag/dotnet-core.html.gz differ diff --git a/tag/dotnet.html b/tag/dotnet.html new file mode 100644 index 000000000..8a2bcf70e --- /dev/null +++ b/tag/dotnet.html @@ -0,0 +1,316 @@ + + + + + + + + DotNet - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/dotnet.html.gz b/tag/dotnet.html.gz new file mode 100644 index 000000000..c7e078ed3 Binary files /dev/null and b/tag/dotnet.html.gz differ diff --git a/tag/ef-core.html b/tag/ef-core.html new file mode 100644 index 000000000..0359d835e --- /dev/null +++ b/tag/ef-core.html @@ -0,0 +1,296 @@ + + + + + + + + EF Core - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/ef-core.html.gz b/tag/ef-core.html.gz new file mode 100644 index 000000000..1c67bbe6a Binary files /dev/null and b/tag/ef-core.html.gz differ diff --git a/tag/entity-framework.html b/tag/entity-framework.html new file mode 100644 index 000000000..d88cf0de8 --- /dev/null +++ b/tag/entity-framework.html @@ -0,0 +1,296 @@ + + + + + + + + Entity Framework - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Entity Framework

+
+ + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/entity-framework.html.gz b/tag/entity-framework.html.gz new file mode 100644 index 000000000..78722ad65 Binary files /dev/null and b/tag/entity-framework.html.gz differ diff --git a/tag/expressjs.html b/tag/expressjs.html new file mode 100644 index 000000000..1d2edc6b8 --- /dev/null +++ b/tag/expressjs.html @@ -0,0 +1,306 @@ + + + + + + + + expressjs - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/expressjs.html.gz b/tag/expressjs.html.gz new file mode 100644 index 000000000..49c8ff4bf Binary files /dev/null and b/tag/expressjs.html.gz differ diff --git a/tag/external-display.html b/tag/external-display.html new file mode 100644 index 000000000..9b3ecd07b --- /dev/null +++ b/tag/external-display.html @@ -0,0 +1,296 @@ + + + + + + + + external display - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

external display

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/external-display.html.gz b/tag/external-display.html.gz new file mode 100644 index 000000000..d7adf6522 Binary files /dev/null and b/tag/external-display.html.gz differ diff --git a/tag/filesreadallbytes.html b/tag/filesreadallbytes.html new file mode 100644 index 000000000..086159b1a --- /dev/null +++ b/tag/filesreadallbytes.html @@ -0,0 +1,296 @@ + + + + + + + + Files.readAllBytes - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Files.readAllBytes

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/filesreadallbytes.html.gz b/tag/filesreadallbytes.html.gz new file mode 100644 index 000000000..58a242e00 Binary files /dev/null and b/tag/filesreadallbytes.html.gz differ diff --git a/tag/firebase.html b/tag/firebase.html new file mode 100644 index 000000000..e35abc0b3 --- /dev/null +++ b/tag/firebase.html @@ -0,0 +1,296 @@ + + + + + + + + firebase - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

firebase

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/firebase.html.gz b/tag/firebase.html.gz new file mode 100644 index 000000000..83e66f92c Binary files /dev/null and b/tag/firebase.html.gz differ diff --git a/tag/firefoxos.html b/tag/firefoxos.html new file mode 100644 index 000000000..5439c199c --- /dev/null +++ b/tag/firefoxos.html @@ -0,0 +1,286 @@ + + + + + + + + FirefoxOS - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

FirefoxOS

+
+ +
+
    +
+
+
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/firefoxos.html.gz b/tag/firefoxos.html.gz new file mode 100644 index 000000000..7e2bd7dda Binary files /dev/null and b/tag/firefoxos.html.gz differ diff --git a/tag/flutter.html b/tag/flutter.html new file mode 100644 index 000000000..f2e80065a --- /dev/null +++ b/tag/flutter.html @@ -0,0 +1,296 @@ + + + + + + + + flutter - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

flutter

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/flutter.html.gz b/tag/flutter.html.gz new file mode 100644 index 000000000..1cba4bccd Binary files /dev/null and b/tag/flutter.html.gz differ diff --git a/tag/getchild-item.html b/tag/getchild-item.html new file mode 100644 index 000000000..164253163 --- /dev/null +++ b/tag/getchild-item.html @@ -0,0 +1,296 @@ + + + + + + + + GetChild-Item - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

GetChild-Item

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/getchild-item.html.gz b/tag/getchild-item.html.gz new file mode 100644 index 000000000..2c254b640 Binary files /dev/null and b/tag/getchild-item.html.gz differ diff --git a/tag/git.html b/tag/git.html new file mode 100644 index 000000000..cc534c66b --- /dev/null +++ b/tag/git.html @@ -0,0 +1,296 @@ + + + + + + + + git - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

git

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/git.html.gz b/tag/git.html.gz new file mode 100644 index 000000000..1b180e323 Binary files /dev/null and b/tag/git.html.gz differ diff --git a/tag/grepora.html b/tag/grepora.html new file mode 100644 index 000000000..8828954be --- /dev/null +++ b/tag/grepora.html @@ -0,0 +1,296 @@ + + + + + + + + Grepora - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Grepora

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/grepora.html.gz b/tag/grepora.html.gz new file mode 100644 index 000000000..6298a5971 Binary files /dev/null and b/tag/grepora.html.gz differ diff --git a/tag/hibernate.html b/tag/hibernate.html new file mode 100644 index 000000000..61a299891 --- /dev/null +++ b/tag/hibernate.html @@ -0,0 +1,296 @@ + + + + + + + + Hibernate - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/hibernate.html.gz b/tag/hibernate.html.gz new file mode 100644 index 000000000..590980aad Binary files /dev/null and b/tag/hibernate.html.gz differ diff --git a/tag/hooks.html b/tag/hooks.html new file mode 100644 index 000000000..f514b26cd --- /dev/null +++ b/tag/hooks.html @@ -0,0 +1,296 @@ + + + + + + + + hooks - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

hooks

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/hooks.html.gz b/tag/hooks.html.gz new file mode 100644 index 000000000..e938a4b9e Binary files /dev/null and b/tag/hooks.html.gz differ diff --git a/tag/html.html b/tag/html.html new file mode 100644 index 000000000..270b654be --- /dev/null +++ b/tag/html.html @@ -0,0 +1,286 @@ + + + + + + + + Html - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Html

+
+ +
+
    +
+
+
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/html.html.gz b/tag/html.html.gz new file mode 100644 index 000000000..53dc5e8f9 Binary files /dev/null and b/tag/html.html.gz differ diff --git a/tag/icmp-pinger-more-than-75.html b/tag/icmp-pinger-more-than-75.html new file mode 100644 index 000000000..55ce08ace --- /dev/null +++ b/tag/icmp-pinger-more-than-75.html @@ -0,0 +1,296 @@ + + + + + + + + icmp pinger more than 75 - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

icmp pinger more than 75

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/icmp-pinger-more-than-75.html.gz b/tag/icmp-pinger-more-than-75.html.gz new file mode 100644 index 000000000..a10e9a65c Binary files /dev/null and b/tag/icmp-pinger-more-than-75.html.gz differ diff --git a/tag/icmp-pinger.html b/tag/icmp-pinger.html new file mode 100644 index 000000000..6434b3ed9 --- /dev/null +++ b/tag/icmp-pinger.html @@ -0,0 +1,296 @@ + + + + + + + + icmp pinger - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

icmp pinger

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/icmp-pinger.html.gz b/tag/icmp-pinger.html.gz new file mode 100644 index 000000000..1e3dd3f0f Binary files /dev/null and b/tag/icmp-pinger.html.gz differ diff --git a/tag/imagemin-pngquant.html b/tag/imagemin-pngquant.html new file mode 100644 index 000000000..a743c0aa9 --- /dev/null +++ b/tag/imagemin-pngquant.html @@ -0,0 +1,306 @@ + + + + + + + + imagemin-pngquant - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/imagemin-pngquant.html.gz b/tag/imagemin-pngquant.html.gz new file mode 100644 index 000000000..6e920d0d9 Binary files /dev/null and b/tag/imagemin-pngquant.html.gz differ diff --git a/tag/imagemin.html b/tag/imagemin.html new file mode 100644 index 000000000..d72db2c2d --- /dev/null +++ b/tag/imagemin.html @@ -0,0 +1,306 @@ + + + + + + + + imagemin - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/imagemin.html.gz b/tag/imagemin.html.gz new file mode 100644 index 000000000..0fe4cb91f Binary files /dev/null and b/tag/imagemin.html.gz differ diff --git a/tag/java.html b/tag/java.html new file mode 100644 index 000000000..7e72194ed --- /dev/null +++ b/tag/java.html @@ -0,0 +1,316 @@ + + + + + + + + Java - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/java.html.gz b/tag/java.html.gz new file mode 100644 index 000000000..49484ea1e Binary files /dev/null and b/tag/java.html.gz differ diff --git a/tag/javanetsocketexception.html b/tag/javanetsocketexception.html new file mode 100644 index 000000000..0158e9f8f --- /dev/null +++ b/tag/javanetsocketexception.html @@ -0,0 +1,296 @@ + + + + + + + + java.net.SocketException - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/javanetsocketexception.html.gz b/tag/javanetsocketexception.html.gz new file mode 100644 index 000000000..400bbada7 Binary files /dev/null and b/tag/javanetsocketexception.html.gz differ diff --git a/tag/linux.html b/tag/linux.html new file mode 100644 index 000000000..dcd72a8e4 --- /dev/null +++ b/tag/linux.html @@ -0,0 +1,296 @@ + + + + + + + + Linux - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ + +
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/linux.html.gz b/tag/linux.html.gz new file mode 100644 index 000000000..a7d841006 Binary files /dev/null and b/tag/linux.html.gz differ diff --git a/tag/low-memory.html b/tag/low-memory.html new file mode 100644 index 000000000..33b3ae4a4 --- /dev/null +++ b/tag/low-memory.html @@ -0,0 +1,296 @@ + + + + + + + + Low memory - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Low memory

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/low-memory.html.gz b/tag/low-memory.html.gz new file mode 100644 index 000000000..c5c12762c Binary files /dev/null and b/tag/low-memory.html.gz differ diff --git a/tag/microservices.html b/tag/microservices.html new file mode 100644 index 000000000..caa832722 --- /dev/null +++ b/tag/microservices.html @@ -0,0 +1,306 @@ + + + + + + + + microservices - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/microservices.html.gz b/tag/microservices.html.gz new file mode 100644 index 000000000..de3409613 Binary files /dev/null and b/tag/microservices.html.gz differ diff --git a/tag/microsoft.html b/tag/microsoft.html new file mode 100644 index 000000000..a03586383 --- /dev/null +++ b/tag/microsoft.html @@ -0,0 +1,296 @@ + + + + + + + + Microsoft - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Microsoft

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/microsoft.html.gz b/tag/microsoft.html.gz new file mode 100644 index 000000000..8cd6874f8 Binary files /dev/null and b/tag/microsoft.html.gz differ diff --git a/tag/monitor-website.html b/tag/monitor-website.html new file mode 100644 index 000000000..b93644ee5 --- /dev/null +++ b/tag/monitor-website.html @@ -0,0 +1,296 @@ + + + + + + + + Monitor Website - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Monitor Website

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/monitor-website.html.gz b/tag/monitor-website.html.gz new file mode 100644 index 000000000..05ce0e8cc Binary files /dev/null and b/tag/monitor-website.html.gz differ diff --git a/tag/mysql-dual-password.html b/tag/mysql-dual-password.html new file mode 100644 index 000000000..4d6abe369 --- /dev/null +++ b/tag/mysql-dual-password.html @@ -0,0 +1,296 @@ + + + + + + + + MySQL Dual Password - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/mysql-dual-password.html.gz b/tag/mysql-dual-password.html.gz new file mode 100644 index 000000000..43f78509b Binary files /dev/null and b/tag/mysql-dual-password.html.gz differ diff --git a/tag/mysql-replication.html b/tag/mysql-replication.html new file mode 100644 index 000000000..8345e821a --- /dev/null +++ b/tag/mysql-replication.html @@ -0,0 +1,296 @@ + + + + + + + + MySQL Replication - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

MySQL Replication

+
+ + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/mysql-replication.html.gz b/tag/mysql-replication.html.gz new file mode 100644 index 000000000..4ec9e4c15 Binary files /dev/null and b/tag/mysql-replication.html.gz differ diff --git a/tag/mysql-restart.html b/tag/mysql-restart.html new file mode 100644 index 000000000..2bbafa4fc --- /dev/null +++ b/tag/mysql-restart.html @@ -0,0 +1,296 @@ + + + + + + + + MySQL Restart - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

MySQL Restart

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/mysql-restart.html.gz b/tag/mysql-restart.html.gz new file mode 100644 index 000000000..f55cc0ec6 Binary files /dev/null and b/tag/mysql-restart.html.gz differ diff --git a/tag/mysql.html b/tag/mysql.html new file mode 100644 index 000000000..b6d2a8c1f --- /dev/null +++ b/tag/mysql.html @@ -0,0 +1,326 @@ + + + + + + + + MySQL - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/mysql.html.gz b/tag/mysql.html.gz new file mode 100644 index 000000000..bd7bd90f5 Binary files /dev/null and b/tag/mysql.html.gz differ diff --git a/tag/net.html b/tag/net.html new file mode 100644 index 000000000..e23b81cca --- /dev/null +++ b/tag/net.html @@ -0,0 +1,296 @@ + + + + + + + + .net - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

.net

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/net.html.gz b/tag/net.html.gz new file mode 100644 index 000000000..221b3d107 Binary files /dev/null and b/tag/net.html.gz differ diff --git a/tag/noclassdeffound.html b/tag/noclassdeffound.html new file mode 100644 index 000000000..0cad6561c --- /dev/null +++ b/tag/noclassdeffound.html @@ -0,0 +1,296 @@ + + + + + + + + NoClassDefFound - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

NoClassDefFound

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/noclassdeffound.html.gz b/tag/noclassdeffound.html.gz new file mode 100644 index 000000000..e47fb5ed6 Binary files /dev/null and b/tag/noclassdeffound.html.gz differ diff --git a/tag/node-js.html b/tag/node-js.html new file mode 100644 index 000000000..2c057d1f8 --- /dev/null +++ b/tag/node-js.html @@ -0,0 +1,306 @@ + + + + + + + + node js - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/node-js.html.gz b/tag/node-js.html.gz new file mode 100644 index 000000000..2e708a00c Binary files /dev/null and b/tag/node-js.html.gz differ diff --git a/tag/nodejs.html b/tag/nodejs.html new file mode 100644 index 000000000..bd98e8193 --- /dev/null +++ b/tag/nodejs.html @@ -0,0 +1,316 @@ + + + + + + + + nodejs - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/nodejs.html.gz b/tag/nodejs.html.gz new file mode 100644 index 000000000..53d793a36 Binary files /dev/null and b/tag/nodejs.html.gz differ diff --git a/tag/openssh.html b/tag/openssh.html new file mode 100644 index 000000000..dafa1b5e4 --- /dev/null +++ b/tag/openssh.html @@ -0,0 +1,296 @@ + + + + + + + + openssh - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

openssh

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/openssh.html.gz b/tag/openssh.html.gz new file mode 100644 index 000000000..479bba4b1 Binary files /dev/null and b/tag/openssh.html.gz differ diff --git a/tag/out-of-memory.html b/tag/out-of-memory.html new file mode 100644 index 000000000..4e0414a2c --- /dev/null +++ b/tag/out-of-memory.html @@ -0,0 +1,296 @@ + + + + + + + + Out of memory - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Out of memory

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/out-of-memory.html.gz b/tag/out-of-memory.html.gz new file mode 100644 index 000000000..bc21e00a1 Binary files /dev/null and b/tag/out-of-memory.html.gz differ diff --git a/tag/outofmemory.html b/tag/outofmemory.html new file mode 100644 index 000000000..b84c37d0b --- /dev/null +++ b/tag/outofmemory.html @@ -0,0 +1,296 @@ + + + + + + + + outOfMemory - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

outOfMemory

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/outofmemory.html.gz b/tag/outofmemory.html.gz new file mode 100644 index 000000000..b65f98a40 Binary files /dev/null and b/tag/outofmemory.html.gz differ diff --git a/tag/parcel.html b/tag/parcel.html new file mode 100644 index 000000000..9e1f454f2 --- /dev/null +++ b/tag/parcel.html @@ -0,0 +1,296 @@ + + + + + + + + parcel - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ + +
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/parcel.html.gz b/tag/parcel.html.gz new file mode 100644 index 000000000..c744bfe07 Binary files /dev/null and b/tag/parcel.html.gz differ diff --git a/tag/poller-proccess-more-than-75.html b/tag/poller-proccess-more-than-75.html new file mode 100644 index 000000000..77810ba05 --- /dev/null +++ b/tag/poller-proccess-more-than-75.html @@ -0,0 +1,296 @@ + + + + + + + + Poller proccess more than 75% - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Poller proccess more than 75%

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/poller-proccess-more-than-75.html.gz b/tag/poller-proccess-more-than-75.html.gz new file mode 100644 index 000000000..e117cec90 Binary files /dev/null and b/tag/poller-proccess-more-than-75.html.gz differ diff --git a/tag/powershell-mail.html b/tag/powershell-mail.html new file mode 100644 index 000000000..508b6c499 --- /dev/null +++ b/tag/powershell-mail.html @@ -0,0 +1,296 @@ + + + + + + + + Powershell mail - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Powershell mail

+
+ + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/powershell-mail.html.gz b/tag/powershell-mail.html.gz new file mode 100644 index 000000000..dd5ad398d Binary files /dev/null and b/tag/powershell-mail.html.gz differ diff --git a/tag/powershell-monitoring.html b/tag/powershell-monitoring.html new file mode 100644 index 000000000..6738868e1 --- /dev/null +++ b/tag/powershell-monitoring.html @@ -0,0 +1,296 @@ + + + + + + + + Powershell monitoring - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Powershell monitoring

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/powershell-monitoring.html.gz b/tag/powershell-monitoring.html.gz new file mode 100644 index 000000000..8f93e94b2 Binary files /dev/null and b/tag/powershell-monitoring.html.gz differ diff --git a/tag/powershell.html b/tag/powershell.html new file mode 100644 index 000000000..c3a6b10f4 --- /dev/null +++ b/tag/powershell.html @@ -0,0 +1,306 @@ + + + + + + + + PowerShell - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/powershell.html.gz b/tag/powershell.html.gz new file mode 100644 index 000000000..3d77c2baa Binary files /dev/null and b/tag/powershell.html.gz differ diff --git a/tag/pre-commit.html b/tag/pre-commit.html new file mode 100644 index 000000000..5228cd903 --- /dev/null +++ b/tag/pre-commit.html @@ -0,0 +1,296 @@ + + + + + + + + pre-commit - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

pre-commit

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/pre-commit.html.gz b/tag/pre-commit.html.gz new file mode 100644 index 000000000..c7fc39d16 Binary files /dev/null and b/tag/pre-commit.html.gz differ diff --git a/tag/protocol-family-unavailable.html b/tag/protocol-family-unavailable.html new file mode 100644 index 000000000..6cea4bd76 --- /dev/null +++ b/tag/protocol-family-unavailable.html @@ -0,0 +1,296 @@ + + + + + + + + Protocol family unavailable - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/protocol-family-unavailable.html.gz b/tag/protocol-family-unavailable.html.gz new file mode 100644 index 000000000..f89dfe3bf Binary files /dev/null and b/tag/protocol-family-unavailable.html.gz differ diff --git a/tag/rabbitmq.html b/tag/rabbitmq.html new file mode 100644 index 000000000..fd0f579f0 --- /dev/null +++ b/tag/rabbitmq.html @@ -0,0 +1,306 @@ + + + + + + + + rabbitmq - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/rabbitmq.html.gz b/tag/rabbitmq.html.gz new file mode 100644 index 000000000..789fa365f Binary files /dev/null and b/tag/rabbitmq.html.gz differ diff --git a/tag/random.html b/tag/random.html new file mode 100644 index 000000000..9d582f8fd --- /dev/null +++ b/tag/random.html @@ -0,0 +1,296 @@ + + + + + + + + Random - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Random

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/random.html.gz b/tag/random.html.gz new file mode 100644 index 000000000..f7df9bb19 Binary files /dev/null and b/tag/random.html.gz differ diff --git a/tag/raspberry.html b/tag/raspberry.html new file mode 100644 index 000000000..8af47bea5 --- /dev/null +++ b/tag/raspberry.html @@ -0,0 +1,286 @@ + + + + + + + + raspberry - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

raspberry

+
+ +
+
    +
+
+
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/raspberry.html.gz b/tag/raspberry.html.gz new file mode 100644 index 000000000..4adc7d884 Binary files /dev/null and b/tag/raspberry.html.gz differ diff --git a/tag/react.html b/tag/react.html new file mode 100644 index 000000000..acd971e2d --- /dev/null +++ b/tag/react.html @@ -0,0 +1,296 @@ + + + + + + + + react - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ + +
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/react.html.gz b/tag/react.html.gz new file mode 100644 index 000000000..707c6399a Binary files /dev/null and b/tag/react.html.gz differ diff --git a/tag/remove-item.html b/tag/remove-item.html new file mode 100644 index 000000000..a327be4e3 --- /dev/null +++ b/tag/remove-item.html @@ -0,0 +1,296 @@ + + + + + + + + Remove-Item - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Remove-Item

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/remove-item.html.gz b/tag/remove-item.html.gz new file mode 100644 index 000000000..03c284bd4 Binary files /dev/null and b/tag/remove-item.html.gz differ diff --git a/tag/replacing-underscore.html b/tag/replacing-underscore.html new file mode 100644 index 000000000..c9e69c032 --- /dev/null +++ b/tag/replacing-underscore.html @@ -0,0 +1,296 @@ + + + + + + + + replacing underscore - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

replacing underscore

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/replacing-underscore.html.gz b/tag/replacing-underscore.html.gz new file mode 100644 index 000000000..30d9e8fe1 Binary files /dev/null and b/tag/replacing-underscore.html.gz differ diff --git a/tag/resource-governor.html b/tag/resource-governor.html new file mode 100644 index 000000000..8b4271bd2 --- /dev/null +++ b/tag/resource-governor.html @@ -0,0 +1,296 @@ + + + + + + + + Resource Governor - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Resource Governor

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/resource-governor.html.gz b/tag/resource-governor.html.gz new file mode 100644 index 000000000..f251d9a37 Binary files /dev/null and b/tag/resource-governor.html.gz differ diff --git a/tag/script.html b/tag/script.html new file mode 100644 index 000000000..8ee78072f --- /dev/null +++ b/tag/script.html @@ -0,0 +1,296 @@ + + + + + + + + Script - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Script

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/script.html.gz b/tag/script.html.gz new file mode 100644 index 000000000..e903b64fb Binary files /dev/null and b/tag/script.html.gz differ diff --git a/tag/shell.html b/tag/shell.html new file mode 100644 index 000000000..7f7c2cee1 --- /dev/null +++ b/tag/shell.html @@ -0,0 +1,326 @@ + + + + + + + + Shell - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/shell.html.gz b/tag/shell.html.gz new file mode 100644 index 000000000..735d320c5 Binary files /dev/null and b/tag/shell.html.gz differ diff --git a/tag/specify-columns.html b/tag/specify-columns.html new file mode 100644 index 000000000..fc149a70b --- /dev/null +++ b/tag/specify-columns.html @@ -0,0 +1,296 @@ + + + + + + + + Specify columns - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Specify columns

+
+ + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/specify-columns.html.gz b/tag/specify-columns.html.gz new file mode 100644 index 000000000..cb5ef432e Binary files /dev/null and b/tag/specify-columns.html.gz differ diff --git a/tag/sqlserver.html b/tag/sqlserver.html new file mode 100644 index 000000000..1159b1e87 --- /dev/null +++ b/tag/sqlserver.html @@ -0,0 +1,316 @@ + + + + + + + + SQLServer - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/sqlserver.html.gz b/tag/sqlserver.html.gz new file mode 100644 index 000000000..d976d0d13 Binary files /dev/null and b/tag/sqlserver.html.gz differ diff --git a/tag/ssh-tunnel.html b/tag/ssh-tunnel.html new file mode 100644 index 000000000..61f6208f6 --- /dev/null +++ b/tag/ssh-tunnel.html @@ -0,0 +1,296 @@ + + + + + + + + ssh tunnel - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

ssh tunnel

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/ssh-tunnel.html.gz b/tag/ssh-tunnel.html.gz new file mode 100644 index 000000000..d5b73ae85 Binary files /dev/null and b/tag/ssh-tunnel.html.gz differ diff --git a/tag/ssh.html b/tag/ssh.html new file mode 100644 index 000000000..2b9f73af8 --- /dev/null +++ b/tag/ssh.html @@ -0,0 +1,296 @@ + + + + + + + + ssh - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

ssh

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/ssh.html.gz b/tag/ssh.html.gz new file mode 100644 index 000000000..dc0e5c0fd Binary files /dev/null and b/tag/ssh.html.gz differ diff --git a/tag/stop-proccess.html b/tag/stop-proccess.html new file mode 100644 index 000000000..84520d9f6 --- /dev/null +++ b/tag/stop-proccess.html @@ -0,0 +1,296 @@ + + + + + + + + Stop-Proccess - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Stop-Proccess

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/stop-proccess.html.gz b/tag/stop-proccess.html.gz new file mode 100644 index 000000000..72bcfc320 Binary files /dev/null and b/tag/stop-proccess.html.gz differ diff --git a/tag/the-database-principal-owns-a-schema.html b/tag/the-database-principal-owns-a-schema.html new file mode 100644 index 000000000..6f5989e28 --- /dev/null +++ b/tag/the-database-principal-owns-a-schema.html @@ -0,0 +1,296 @@ + + + + + + + + The database principal owns a schema - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

The database principal owns a schema

+
+ + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/the-database-principal-owns-a-schema.html.gz b/tag/the-database-principal-owns-a-schema.html.gz new file mode 100644 index 000000000..06f202b2b Binary files /dev/null and b/tag/the-database-principal-owns-a-schema.html.gz differ diff --git a/tag/through-firewall.html b/tag/through-firewall.html new file mode 100644 index 000000000..2781cbce4 --- /dev/null +++ b/tag/through-firewall.html @@ -0,0 +1,296 @@ + + + + + + + + through firewall - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

through firewall

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/through-firewall.html.gz b/tag/through-firewall.html.gz new file mode 100644 index 000000000..672278547 Binary files /dev/null and b/tag/through-firewall.html.gz differ diff --git a/tag/time-schedule-blocking.html b/tag/time-schedule-blocking.html new file mode 100644 index 000000000..7717f3ec4 --- /dev/null +++ b/tag/time-schedule-blocking.html @@ -0,0 +1,296 @@ + + + + + + + + Time Schedule blocking - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Time Schedule blocking

+
+ + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/time-schedule-blocking.html.gz b/tag/time-schedule-blocking.html.gz new file mode 100644 index 000000000..5387f1f4a Binary files /dev/null and b/tag/time-schedule-blocking.html.gz differ diff --git a/tag/tools.html b/tag/tools.html new file mode 100644 index 000000000..b12f0105a --- /dev/null +++ b/tag/tools.html @@ -0,0 +1,286 @@ + + + + + + + + Tools - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Tools

+
+ +
+
    +
+
+
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/tools.html.gz b/tag/tools.html.gz new file mode 100644 index 000000000..a9dd0e0d4 Binary files /dev/null and b/tag/tools.html.gz differ diff --git a/tag/tunnel.html b/tag/tunnel.html new file mode 100644 index 000000000..2081f19e8 --- /dev/null +++ b/tag/tunnel.html @@ -0,0 +1,296 @@ + + + + + + + + tunnel - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

tunnel

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/tunnel.html.gz b/tag/tunnel.html.gz new file mode 100644 index 000000000..38e3f4798 Binary files /dev/null and b/tag/tunnel.html.gz differ diff --git a/tag/user.html b/tag/user.html new file mode 100644 index 000000000..66612e597 --- /dev/null +++ b/tag/user.html @@ -0,0 +1,306 @@ + + + + + + + + User - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/user.html.gz b/tag/user.html.gz new file mode 100644 index 000000000..c32a0b8fd Binary files /dev/null and b/tag/user.html.gz differ diff --git a/tag/wildfly.html b/tag/wildfly.html new file mode 100644 index 000000000..9dc693dff --- /dev/null +++ b/tag/wildfly.html @@ -0,0 +1,296 @@ + + + + + + + + WildFly - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/wildfly.html.gz b/tag/wildfly.html.gz new file mode 100644 index 000000000..372ceb0ac Binary files /dev/null and b/tag/wildfly.html.gz differ diff --git a/tag/yeoman.html b/tag/yeoman.html new file mode 100644 index 000000000..7460a2752 --- /dev/null +++ b/tag/yeoman.html @@ -0,0 +1,296 @@ + + + + + + + + yeoman - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ + +
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/yeoman.html.gz b/tag/yeoman.html.gz new file mode 100644 index 000000000..ca264b7f8 Binary files /dev/null and b/tag/yeoman.html.gz differ diff --git a/tag/zabbix-poller.html b/tag/zabbix-poller.html new file mode 100644 index 000000000..136a7d3c3 --- /dev/null +++ b/tag/zabbix-poller.html @@ -0,0 +1,296 @@ + + + + + + + + Zabbix Poller - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Zabbix Poller

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/zabbix-poller.html.gz b/tag/zabbix-poller.html.gz new file mode 100644 index 000000000..56cafe829 Binary files /dev/null and b/tag/zabbix-poller.html.gz differ diff --git a/tag/zabbix-server.html b/tag/zabbix-server.html new file mode 100644 index 000000000..58bfd17bf --- /dev/null +++ b/tag/zabbix-server.html @@ -0,0 +1,296 @@ + + + + + + + + Zabbix Server - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+

Zabbix Server

+
+ + +
+
+
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/zabbix-server.html.gz b/tag/zabbix-server.html.gz new file mode 100644 index 000000000..1b25c2e6f Binary files /dev/null and b/tag/zabbix-server.html.gz differ diff --git a/tag/zabbix.html b/tag/zabbix.html new file mode 100644 index 000000000..2af46206a --- /dev/null +++ b/tag/zabbix.html @@ -0,0 +1,326 @@ + + + + + + + + Zabbix - Sipmann + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tag/zabbix.html.gz b/tag/zabbix.html.gz new file mode 100644 index 000000000..aaa22fc89 Binary files /dev/null and b/tag/zabbix.html.gz differ diff --git a/tags.html b/tags.html new file mode 100644 index 000000000..388fabb31 --- /dev/null +++ b/tags.html @@ -0,0 +1,381 @@ + + + + + + + + Sipmann - Tags + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tags.html.gz b/tags.html.gz new file mode 100644 index 000000000..351568eea Binary files /dev/null and b/tags.html.gz differ diff --git a/the-power-of-powershell.html b/the-power-of-powershell.html new file mode 100644 index 000000000..41a6db842 --- /dev/null +++ b/the-power-of-powershell.html @@ -0,0 +1,595 @@ + + + + + + + + The power of PowerShell - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

The power of PowerShell

+
+ +
+
+ +
+

As a long time Linux user, I've automated a few things with bash scripts and stayed away from PowerShell... I've moved to a Windows environment a few years ago and still, haven gave a shot to PS. But why not? I've made a few scripts to automate some tasks at a Protheus server.

+

I found the PS scripts being easy to read and understand. Bellow, we have a script to remove files filtering their extension (or no extension at all like the following script).

+
Get-ChildItem "C:\TOTVS\protheus_data\system" -File -Filter *. | Move-Item -Force -Destination { 
+    <# Diretory where the files will be moved. You can use Date formats to help name it #>
+    <# LastWriteTime proprtie from the current file #>
+    $dir = "C:\bad_files\{0:yyyy\\MM\\dd}" -f $_.LastWriteTime
+    $null = mkdir $dir -Force 
+    "$dir\$($_.Name)"
+}
+
+ +

Have you ever been in the need to remove files based on other file content? Bello a script where I read a file that has the names of files that I want to remove.

+
foreach($line in Get-Content .\Desktop\bad_files.txt) {
+    if (Test-Path('\\x.y.z.a\c$\TOTVS\protheus_data\xmls\'+$line+'.xml')) {
+        Remove-Item('\\x.y.z.a\c$\TOTVS\protheus_data\xmls\'+$line+'.xml')
+    } else {
+        echo $line + ' - File not found'
+    }
+}
+
+ +

And a bonus script to stop/start services (if you handle some Protheus Server, you know why I do that).

+
$servicesNames = 'app_main',
+    'app_worker1',
+    'app_worker2',
+    'app_worker3',
+    'app_worker4',
+    'app_worker5'
+
+Write-host "Stoping Services"
+Write-host "--------------------------"
+
+foreach ($srv in $servicesNames) {
+    Write-host "Stopping: " + $srv
+    $SrvPID = (get-wmiobject win32_service | where { $_.name -eq $srv}).processID
+    Write-host "PID: " + $SrvPID
+
+    <# Force if the proccess is stucked #>
+    Stop-Process $SrvPID -Force
+    Write-host "PDI " + $SrvPID + " stopped"
+}
+
+
+Write-host "Starting Services"
+Write-host "--------------------------"
+
+foreach ($srv in $servicesNames) {
+    Write-host "Starting: " + $srv
+    Start-Service $srv
+}
+
+ +

Do you have any automated script? Share with us :)

+
+ + +
+
+

Translations:

+ +
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/the-power-of-powershell.html.gz b/the-power-of-powershell.html.gz new file mode 100644 index 000000000..2a02bf976 Binary files /dev/null and b/the-power-of-powershell.html.gz differ diff --git a/theme/css/pygments/autumn.css b/theme/css/pygments/autumn.css new file mode 100644 index 000000000..4709a01b5 --- /dev/null +++ b/theme/css/pygments/autumn.css @@ -0,0 +1,59 @@ +.highlight pre .hll { background-color: #ffffcc } +.highlight pre, .highlighttable pre { background: #ffffff; } +.highlight pre .c { color: #aaaaaa; font-style: italic } /* Comment */ +.highlight pre .err { color: #FF0000; background-color: #FFAAAA } /* Error */ +.highlight pre .k { color: #0000aa } /* Keyword */ +.highlight pre .cm { color: #aaaaaa; font-style: italic } /* Comment.Multiline */ +.highlight pre .cp { color: #4c8317 } /* Comment.Preproc */ +.highlight pre .c1 { color: #aaaaaa; font-style: italic } /* Comment.Single */ +.highlight pre .cs { color: #0000aa; font-style: italic } /* Comment.Special */ +.highlight pre .gd { color: #aa0000 } /* Generic.Deleted */ +.highlight pre .ge { font-style: italic } /* Generic.Emph */ +.highlight pre .gr { color: #aa0000 } /* Generic.Error */ +.highlight pre .gh { color: #000080; font-weight: bold } /* Generic.Heading */ +.highlight pre .gi { color: #00aa00 } /* Generic.Inserted */ +.highlight pre .go { color: #888888 } /* Generic.Output */ +.highlight pre .gp { color: #555555 } /* Generic.Prompt */ +.highlight pre .gs { font-weight: bold } /* Generic.Strong */ +.highlight pre .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +.highlight pre .gt { color: #aa0000 } /* Generic.Traceback */ +.highlight pre .kc { color: #0000aa } /* Keyword.Constant */ +.highlight pre .kd { color: #0000aa } /* Keyword.Declaration */ +.highlight pre .kn { color: #0000aa } /* Keyword.Namespace */ +.highlight pre .kp { color: #0000aa } /* Keyword.Pseudo */ +.highlight pre .kr { color: #0000aa } /* Keyword.Reserved */ +.highlight pre .kt { color: #00aaaa } /* Keyword.Type */ +.highlight pre .m { color: #009999 } /* Literal.Number */ +.highlight pre .s { color: #aa5500 } /* Literal.String */ +.highlight pre .na { color: #1e90ff } /* Name.Attribute */ +.highlight pre .nb { color: #00aaaa } /* Name.Builtin */ +.highlight pre .nc { color: #00aa00; text-decoration: underline } /* Name.Class */ +.highlight pre .no { color: #aa0000 } /* Name.Constant */ +.highlight pre .nd { color: #888888 } /* Name.Decorator */ +.highlight pre .ni { color: #880000; font-weight: bold } /* Name.Entity */ +.highlight pre .nf { color: #00aa00 } /* Name.Function */ +.highlight pre .nn { color: #00aaaa; text-decoration: underline } /* Name.Namespace */ +.highlight pre .nt { color: #1e90ff; font-weight: bold } /* Name.Tag */ +.highlight pre .nv { color: #aa0000 } /* Name.Variable */ +.highlight pre .ow { color: #0000aa } /* Operator.Word */ +.highlight pre .w { color: #bbbbbb } /* Text.Whitespace */ +.highlight pre .mf { color: #009999 } /* Literal.Number.Float */ +.highlight pre .mh { color: #009999 } /* Literal.Number.Hex */ +.highlight pre .mi { color: #009999 } /* Literal.Number.Integer */ +.highlight pre .mo { color: #009999 } /* Literal.Number.Oct */ +.highlight pre .sb { color: #aa5500 } /* Literal.String.Backtick */ +.highlight pre .sc { color: #aa5500 } /* Literal.String.Char */ +.highlight pre .sd { color: #aa5500 } /* Literal.String.Doc */ +.highlight pre .s2 { color: #aa5500 } /* Literal.String.Double */ +.highlight pre .se { color: #aa5500 } /* Literal.String.Escape */ +.highlight pre .sh { color: #aa5500 } /* Literal.String.Heredoc */ +.highlight pre .si { color: #aa5500 } /* Literal.String.Interpol */ +.highlight pre .sx { color: #aa5500 } /* Literal.String.Other */ +.highlight pre .sr { color: #009999 } /* Literal.String.Regex */ +.highlight pre .s1 { color: #aa5500 } /* Literal.String.Single */ +.highlight pre .ss { color: #0000aa } /* Literal.String.Symbol */ +.highlight pre .bp { color: #00aaaa } /* Name.Builtin.Pseudo */ +.highlight pre .vc { color: #aa0000 } /* Name.Variable.Class */ +.highlight pre .vg { color: #aa0000 } /* Name.Variable.Global */ +.highlight pre .vi { color: #aa0000 } /* Name.Variable.Instance */ +.highlight pre .il { color: #009999 } /* Literal.Number.Integer.Long */ diff --git a/theme/css/pygments/autumn.css.gz b/theme/css/pygments/autumn.css.gz new file mode 100644 index 000000000..f19e93e2a Binary files /dev/null and b/theme/css/pygments/autumn.css.gz differ diff --git a/theme/css/pygments/borland.css b/theme/css/pygments/borland.css new file mode 100644 index 000000000..557adf99e --- /dev/null +++ b/theme/css/pygments/borland.css @@ -0,0 +1,47 @@ +.highlight pre .hll { background-color: #ffffcc } +.highlight pre, .highlighttable pre { background: #ffffff; } +.highlight pre .c { color: #008800; font-style: italic } /* Comment */ +.highlight pre .err { color: #a61717; background-color: #e3d2d2 } /* Error */ +.highlight pre .k { color: #000080; font-weight: bold } /* Keyword */ +.highlight pre .cm { color: #008800; font-style: italic } /* Comment.Multiline */ +.highlight pre .cp { color: #008080 } /* Comment.Preproc */ +.highlight pre .c1 { color: #008800; font-style: italic } /* Comment.Single */ +.highlight pre .cs { color: #008800; font-weight: bold } /* Comment.Special */ +.highlight pre .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ +.highlight pre .ge { font-style: italic } /* Generic.Emph */ +.highlight pre .gr { color: #aa0000 } /* Generic.Error */ +.highlight pre .gh { color: #999999 } /* Generic.Heading */ +.highlight pre .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ +.highlight pre .go { color: #888888 } /* Generic.Output */ +.highlight pre .gp { color: #555555 } /* Generic.Prompt */ +.highlight pre .gs { font-weight: bold } /* Generic.Strong */ +.highlight pre .gu { color: #aaaaaa } /* Generic.Subheading */ +.highlight pre .gt { color: #aa0000 } /* Generic.Traceback */ +.highlight pre .kc { color: #000080; font-weight: bold } /* Keyword.Constant */ +.highlight pre .kd { color: #000080; font-weight: bold } /* Keyword.Declaration */ +.highlight pre .kn { color: #000080; font-weight: bold } /* Keyword.Namespace */ +.highlight pre .kp { color: #000080; font-weight: bold } /* Keyword.Pseudo */ +.highlight pre .kr { color: #000080; font-weight: bold } /* Keyword.Reserved */ +.highlight pre .kt { color: #000080; font-weight: bold } /* Keyword.Type */ +.highlight pre .m { color: #0000FF } /* Literal.Number */ +.highlight pre .s { color: #0000FF } /* Literal.String */ +.highlight pre .na { color: #FF0000 } /* Name.Attribute */ +.highlight pre .nt { color: #000080; font-weight: bold } /* Name.Tag */ +.highlight pre .ow { font-weight: bold } /* Operator.Word */ +.highlight pre .w { color: #bbbbbb } /* Text.Whitespace */ +.highlight pre .mf { color: #0000FF } /* Literal.Number.Float */ +.highlight pre .mh { color: #0000FF } /* Literal.Number.Hex */ +.highlight pre .mi { color: #0000FF } /* Literal.Number.Integer */ +.highlight pre .mo { color: #0000FF } /* Literal.Number.Oct */ +.highlight pre .sb { color: #0000FF } /* Literal.String.Backtick */ +.highlight pre .sc { color: #800080 } /* Literal.String.Char */ +.highlight pre .sd { color: #0000FF } /* Literal.String.Doc */ +.highlight pre .s2 { color: #0000FF } /* Literal.String.Double */ +.highlight pre .se { color: #0000FF } /* Literal.String.Escape */ +.highlight pre .sh { color: #0000FF } /* Literal.String.Heredoc */ +.highlight pre .si { color: #0000FF } /* Literal.String.Interpol */ +.highlight pre .sx { color: #0000FF } /* Literal.String.Other */ +.highlight pre .sr { color: #0000FF } /* Literal.String.Regex */ +.highlight pre .s1 { color: #0000FF } /* Literal.String.Single */ +.highlight pre .ss { color: #0000FF } /* Literal.String.Symbol */ +.highlight pre .il { color: #0000FF } /* Literal.Number.Integer.Long */ diff --git a/theme/css/pygments/borland.css.gz b/theme/css/pygments/borland.css.gz new file mode 100644 index 000000000..002f94f77 Binary files /dev/null and b/theme/css/pygments/borland.css.gz differ diff --git a/theme/css/pygments/bw.css b/theme/css/pygments/bw.css new file mode 100644 index 000000000..38b3b2bc6 --- /dev/null +++ b/theme/css/pygments/bw.css @@ -0,0 +1,35 @@ +.highlight pre .hll { background-color: #ffffcc } +.highlight pre, .highlighttable pre { background: #ffffff; } +.highlight pre .c { font-style: italic } /* Comment */ +.highlight pre .err { border: 1px solid #FF0000 } /* Error */ +.highlight pre .k { font-weight: bold } /* Keyword */ +.highlight pre .cm { font-style: italic } /* Comment.Multiline */ +.highlight pre .c1 { font-style: italic } /* Comment.Single */ +.highlight pre .cs { font-style: italic } /* Comment.Special */ +.highlight pre .ge { font-style: italic } /* Generic.Emph */ +.highlight pre .gh { font-weight: bold } /* Generic.Heading */ +.highlight pre .gp { font-weight: bold } /* Generic.Prompt */ +.highlight pre .gs { font-weight: bold } /* Generic.Strong */ +.highlight pre .gu { font-weight: bold } /* Generic.Subheading */ +.highlight pre .kc { font-weight: bold } /* Keyword.Constant */ +.highlight pre .kd { font-weight: bold } /* Keyword.Declaration */ +.highlight pre .kn { font-weight: bold } /* Keyword.Namespace */ +.highlight pre .kr { font-weight: bold } /* Keyword.Reserved */ +.highlight pre .s { font-style: italic } /* Literal.String */ +.highlight pre .nc { font-weight: bold } /* Name.Class */ +.highlight pre .ni { font-weight: bold } /* Name.Entity */ +.highlight pre .ne { font-weight: bold } /* Name.Exception */ +.highlight pre .nn { font-weight: bold } /* Name.Namespace */ +.highlight pre .nt { font-weight: bold } /* Name.Tag */ +.highlight pre .ow { font-weight: bold } /* Operator.Word */ +.highlight pre .sb { font-style: italic } /* Literal.String.Backtick */ +.highlight pre .sc { font-style: italic } /* Literal.String.Char */ +.highlight pre .sd { font-style: italic } /* Literal.String.Doc */ +.highlight pre .s2 { font-style: italic } /* Literal.String.Double */ +.highlight pre .se { font-weight: bold; font-style: italic } /* Literal.String.Escape */ +.highlight pre .sh { font-style: italic } /* Literal.String.Heredoc */ +.highlight pre .si { font-weight: bold; font-style: italic } /* Literal.String.Interpol */ +.highlight pre .sx { font-style: italic } /* Literal.String.Other */ +.highlight pre .sr { font-style: italic } /* Literal.String.Regex */ +.highlight pre .s1 { font-style: italic } /* Literal.String.Single */ +.highlight pre .ss { font-style: italic } /* Literal.String.Symbol */ diff --git a/theme/css/pygments/bw.css.gz b/theme/css/pygments/bw.css.gz new file mode 100644 index 000000000..f360442e5 Binary files /dev/null and b/theme/css/pygments/bw.css.gz differ diff --git a/theme/css/pygments/colorful.css b/theme/css/pygments/colorful.css new file mode 100644 index 000000000..8c5ca1058 --- /dev/null +++ b/theme/css/pygments/colorful.css @@ -0,0 +1,62 @@ +.highlight pre .hll { background-color: #ffffcc } +.highlight pre, .highlighttable pre { background: #ffffff; } +.highlight pre .c { color: #888888 } /* Comment */ +.highlight pre .err { color: #FF0000; background-color: #FFAAAA } /* Error */ +.highlight pre .k { color: #008800; font-weight: bold } /* Keyword */ +.highlight pre .o { color: #333333 } /* Operator */ +.highlight pre .cm { color: #888888 } /* Comment.Multiline */ +.highlight pre .cp { color: #557799 } /* Comment.Preproc */ +.highlight pre .c1 { color: #888888 } /* Comment.Single */ +.highlight pre .cs { color: #cc0000; font-weight: bold } /* Comment.Special */ +.highlight pre .gd { color: #A00000 } /* Generic.Deleted */ +.highlight pre .ge { font-style: italic } /* Generic.Emph */ +.highlight pre .gr { color: #FF0000 } /* Generic.Error */ +.highlight pre .gh { color: #000080; font-weight: bold } /* Generic.Heading */ +.highlight pre .gi { color: #00A000 } /* Generic.Inserted */ +.highlight pre .go { color: #888888 } /* Generic.Output */ +.highlight pre .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */ +.highlight pre .gs { font-weight: bold } /* Generic.Strong */ +.highlight pre .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +.highlight pre .gt { color: #0044DD } /* Generic.Traceback */ +.highlight pre .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ +.highlight pre .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ +.highlight pre .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ +.highlight pre .kp { color: #003388; font-weight: bold } /* Keyword.Pseudo */ +.highlight pre .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ +.highlight pre .kt { color: #333399; font-weight: bold } /* Keyword.Type */ +.highlight pre .m { color: #6600EE; font-weight: bold } /* Literal.Number */ +.highlight pre .s { background-color: #fff0f0 } /* Literal.String */ +.highlight pre .na { color: #0000CC } /* Name.Attribute */ +.highlight pre .nb { color: #007020 } /* Name.Builtin */ +.highlight pre .nc { color: #BB0066; font-weight: bold } /* Name.Class */ +.highlight pre .no { color: #003366; font-weight: bold } /* Name.Constant */ +.highlight pre .nd { color: #555555; font-weight: bold } /* Name.Decorator */ +.highlight pre .ni { color: #880000; font-weight: bold } /* Name.Entity */ +.highlight pre .ne { color: #FF0000; font-weight: bold } /* Name.Exception */ +.highlight pre .nf { color: #0066BB; font-weight: bold } /* Name.Function */ +.highlight pre .nl { color: #997700; font-weight: bold } /* Name.Label */ +.highlight pre .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */ +.highlight pre .nt { color: #007700 } /* Name.Tag */ +.highlight pre .nv { color: #996633 } /* Name.Variable */ +.highlight pre .ow { color: #000000; font-weight: bold } /* Operator.Word */ +.highlight pre .w { color: #bbbbbb } /* Text.Whitespace */ +.highlight pre .mf { color: #6600EE; font-weight: bold } /* Literal.Number.Float */ +.highlight pre .mh { color: #005588; font-weight: bold } /* Literal.Number.Hex */ +.highlight pre .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ +.highlight pre .mo { color: #4400EE; font-weight: bold } /* Literal.Number.Oct */ +.highlight pre .sb { background-color: #fff0f0 } /* Literal.String.Backtick */ +.highlight pre .sc { color: #0044DD } /* Literal.String.Char */ +.highlight pre .sd { color: #DD4422 } /* Literal.String.Doc */ +.highlight pre .s2 { background-color: #fff0f0 } /* Literal.String.Double */ +.highlight pre .se { color: #666666; font-weight: bold; background-color: #fff0f0 } /* Literal.String.Escape */ +.highlight pre .sh { background-color: #fff0f0 } /* Literal.String.Heredoc */ +.highlight pre .si { background-color: #eeeeee } /* Literal.String.Interpol */ +.highlight pre .sx { color: #DD2200; background-color: #fff0f0 } /* Literal.String.Other */ +.highlight pre .sr { color: #000000; background-color: #fff0ff } /* Literal.String.Regex */ +.highlight pre .s1 { background-color: #fff0f0 } /* Literal.String.Single */ +.highlight pre .ss { color: #AA6600 } /* Literal.String.Symbol */ +.highlight pre .bp { color: #007020 } /* Name.Builtin.Pseudo */ +.highlight pre .vc { color: #336699 } /* Name.Variable.Class */ +.highlight pre .vg { color: #dd7700; font-weight: bold } /* Name.Variable.Global */ +.highlight pre .vi { color: #3333BB } /* Name.Variable.Instance */ +.highlight pre .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */ diff --git a/theme/css/pygments/colorful.css.gz b/theme/css/pygments/colorful.css.gz new file mode 100644 index 000000000..b1eb6c1ad Binary files /dev/null and b/theme/css/pygments/colorful.css.gz differ diff --git a/theme/css/pygments/default.css b/theme/css/pygments/default.css new file mode 100644 index 000000000..6a340c79f --- /dev/null +++ b/theme/css/pygments/default.css @@ -0,0 +1,62 @@ +.highlight pre .hll { background-color: #ffffcc } +.highlight pre, .highlighttable pre { background: #f8f8f8; } +.highlight pre .c { color: #408080; font-style: italic } /* Comment */ +.highlight pre .err { border: 1px solid #FF0000 } /* Error */ +.highlight pre .k { color: #008000; font-weight: bold } /* Keyword */ +.highlight pre .o { color: #666666 } /* Operator */ +.highlight pre .cm { color: #408080; font-style: italic } /* Comment.Multiline */ +.highlight pre .cp { color: #BC7A00 } /* Comment.Preproc */ +.highlight pre .c1 { color: #408080; font-style: italic } /* Comment.Single */ +.highlight pre .cs { color: #408080; font-style: italic } /* Comment.Special */ +.highlight pre .gd { color: #A00000 } /* Generic.Deleted */ +.highlight pre .ge { font-style: italic } /* Generic.Emph */ +.highlight pre .gr { color: #FF0000 } /* Generic.Error */ +.highlight pre .gh { color: #000080; font-weight: bold } /* Generic.Heading */ +.highlight pre .gi { color: #00A000 } /* Generic.Inserted */ +.highlight pre .go { color: #888888 } /* Generic.Output */ +.highlight pre .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ +.highlight pre .gs { font-weight: bold } /* Generic.Strong */ +.highlight pre .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +.highlight pre .gt { color: #0044DD } /* Generic.Traceback */ +.highlight pre .kc { color: #008000; font-weight: bold } /* Keyword.Constant */ +.highlight pre .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */ +.highlight pre .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */ +.highlight pre .kp { color: #008000 } /* Keyword.Pseudo */ +.highlight pre .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */ +.highlight pre .kt { color: #B00040 } /* Keyword.Type */ +.highlight pre .m { color: #666666 } /* Literal.Number */ +.highlight pre .s { color: #BA2121 } /* Literal.String */ +.highlight pre .na { color: #7D9029 } /* Name.Attribute */ +.highlight pre .nb { color: #008000 } /* Name.Builtin */ +.highlight pre .nc { color: #0000FF; font-weight: bold } /* Name.Class */ +.highlight pre .no { color: #880000 } /* Name.Constant */ +.highlight pre .nd { color: #AA22FF } /* Name.Decorator */ +.highlight pre .ni { color: #999999; font-weight: bold } /* Name.Entity */ +.highlight pre .ne { color: #D2413A; font-weight: bold } /* Name.Exception */ +.highlight pre .nf { color: #0000FF } /* Name.Function */ +.highlight pre .nl { color: #A0A000 } /* Name.Label */ +.highlight pre .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ +.highlight pre .nt { color: #008000; font-weight: bold } /* Name.Tag */ +.highlight pre .nv { color: #19177C } /* Name.Variable */ +.highlight pre .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ +.highlight pre .w { color: #bbbbbb } /* Text.Whitespace */ +.highlight pre .mf { color: #666666 } /* Literal.Number.Float */ +.highlight pre .mh { color: #666666 } /* Literal.Number.Hex */ +.highlight pre .mi { color: #666666 } /* Literal.Number.Integer */ +.highlight pre .mo { color: #666666 } /* Literal.Number.Oct */ +.highlight pre .sb { color: #BA2121 } /* Literal.String.Backtick */ +.highlight pre .sc { color: #BA2121 } /* Literal.String.Char */ +.highlight pre .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */ +.highlight pre .s2 { color: #BA2121 } /* Literal.String.Double */ +.highlight pre .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */ +.highlight pre .sh { color: #BA2121 } /* Literal.String.Heredoc */ +.highlight pre .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */ +.highlight pre .sx { color: #008000 } /* Literal.String.Other */ +.highlight pre .sr { color: #BB6688 } /* Literal.String.Regex */ +.highlight pre .s1 { color: #BA2121 } /* Literal.String.Single */ +.highlight pre .ss { color: #19177C } /* Literal.String.Symbol */ +.highlight pre .bp { color: #008000 } /* Name.Builtin.Pseudo */ +.highlight pre .vc { color: #19177C } /* Name.Variable.Class */ +.highlight pre .vg { color: #19177C } /* Name.Variable.Global */ +.highlight pre .vi { color: #19177C } /* Name.Variable.Instance */ +.highlight pre .il { color: #666666 } /* Literal.Number.Integer.Long */ diff --git a/theme/css/pygments/default.css.gz b/theme/css/pygments/default.css.gz new file mode 100644 index 000000000..85f6896d1 Binary files /dev/null and b/theme/css/pygments/default.css.gz differ diff --git a/theme/css/pygments/emacs.css b/theme/css/pygments/emacs.css new file mode 100644 index 000000000..8a974f21d --- /dev/null +++ b/theme/css/pygments/emacs.css @@ -0,0 +1,62 @@ +.highlight pre .hll { background-color: #ffffcc } +.highlight pre, .highlighttable pre { background: #f8f8f8; } +.highlight pre .c { color: #008800; font-style: italic } /* Comment */ +.highlight pre .err { border: 1px solid #FF0000 } /* Error */ +.highlight pre .k { color: #AA22FF; font-weight: bold } /* Keyword */ +.highlight pre .o { color: #666666 } /* Operator */ +.highlight pre .cm { color: #008800; font-style: italic } /* Comment.Multiline */ +.highlight pre .cp { color: #008800 } /* Comment.Preproc */ +.highlight pre .c1 { color: #008800; font-style: italic } /* Comment.Single */ +.highlight pre .cs { color: #008800; font-weight: bold } /* Comment.Special */ +.highlight pre .gd { color: #A00000 } /* Generic.Deleted */ +.highlight pre .ge { font-style: italic } /* Generic.Emph */ +.highlight pre .gr { color: #FF0000 } /* Generic.Error */ +.highlight pre .gh { color: #000080; font-weight: bold } /* Generic.Heading */ +.highlight pre .gi { color: #00A000 } /* Generic.Inserted */ +.highlight pre .go { color: #888888 } /* Generic.Output */ +.highlight pre .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ +.highlight pre .gs { font-weight: bold } /* Generic.Strong */ +.highlight pre .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +.highlight pre .gt { color: #0044DD } /* Generic.Traceback */ +.highlight pre .kc { color: #AA22FF; font-weight: bold } /* Keyword.Constant */ +.highlight pre .kd { color: #AA22FF; font-weight: bold } /* Keyword.Declaration */ +.highlight pre .kn { color: #AA22FF; font-weight: bold } /* Keyword.Namespace */ +.highlight pre .kp { color: #AA22FF } /* Keyword.Pseudo */ +.highlight pre .kr { color: #AA22FF; font-weight: bold } /* Keyword.Reserved */ +.highlight pre .kt { color: #00BB00; font-weight: bold } /* Keyword.Type */ +.highlight pre .m { color: #666666 } /* Literal.Number */ +.highlight pre .s { color: #BB4444 } /* Literal.String */ +.highlight pre .na { color: #BB4444 } /* Name.Attribute */ +.highlight pre .nb { color: #AA22FF } /* Name.Builtin */ +.highlight pre .nc { color: #0000FF } /* Name.Class */ +.highlight pre .no { color: #880000 } /* Name.Constant */ +.highlight pre .nd { color: #AA22FF } /* Name.Decorator */ +.highlight pre .ni { color: #999999; font-weight: bold } /* Name.Entity */ +.highlight pre .ne { color: #D2413A; font-weight: bold } /* Name.Exception */ +.highlight pre .nf { color: #00A000 } /* Name.Function */ +.highlight pre .nl { color: #A0A000 } /* Name.Label */ +.highlight pre .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ +.highlight pre .nt { color: #008000; font-weight: bold } /* Name.Tag */ +.highlight pre .nv { color: #B8860B } /* Name.Variable */ +.highlight pre .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ +.highlight pre .w { color: #bbbbbb } /* Text.Whitespace */ +.highlight pre .mf { color: #666666 } /* Literal.Number.Float */ +.highlight pre .mh { color: #666666 } /* Literal.Number.Hex */ +.highlight pre .mi { color: #666666 } /* Literal.Number.Integer */ +.highlight pre .mo { color: #666666 } /* Literal.Number.Oct */ +.highlight pre .sb { color: #BB4444 } /* Literal.String.Backtick */ +.highlight pre .sc { color: #BB4444 } /* Literal.String.Char */ +.highlight pre .sd { color: #BB4444; font-style: italic } /* Literal.String.Doc */ +.highlight pre .s2 { color: #BB4444 } /* Literal.String.Double */ +.highlight pre .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */ +.highlight pre .sh { color: #BB4444 } /* Literal.String.Heredoc */ +.highlight pre .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */ +.highlight pre .sx { color: #008000 } /* Literal.String.Other */ +.highlight pre .sr { color: #BB6688 } /* Literal.String.Regex */ +.highlight pre .s1 { color: #BB4444 } /* Literal.String.Single */ +.highlight pre .ss { color: #B8860B } /* Literal.String.Symbol */ +.highlight pre .bp { color: #AA22FF } /* Name.Builtin.Pseudo */ +.highlight pre .vc { color: #B8860B } /* Name.Variable.Class */ +.highlight pre .vg { color: #B8860B } /* Name.Variable.Global */ +.highlight pre .vi { color: #B8860B } /* Name.Variable.Instance */ +.highlight pre .il { color: #666666 } /* Literal.Number.Integer.Long */ diff --git a/theme/css/pygments/emacs.css.gz b/theme/css/pygments/emacs.css.gz new file mode 100644 index 000000000..2a9bfcdc9 Binary files /dev/null and b/theme/css/pygments/emacs.css.gz differ diff --git a/theme/css/pygments/friendly.css b/theme/css/pygments/friendly.css new file mode 100644 index 000000000..3f52d3de6 --- /dev/null +++ b/theme/css/pygments/friendly.css @@ -0,0 +1,62 @@ +.highlight pre .hll { background-color: #ffffcc } +.highlight pre, .highlighttable pre { background: #f0f0f0; } +.highlight pre .c { color: #60a0b0; font-style: italic } /* Comment */ +.highlight pre .err { border: 1px solid #FF0000 } /* Error */ +.highlight pre .k { color: #007020; font-weight: bold } /* Keyword */ +.highlight pre .o { color: #666666 } /* Operator */ +.highlight pre .cm { color: #60a0b0; font-style: italic } /* Comment.Multiline */ +.highlight pre .cp { color: #007020 } /* Comment.Preproc */ +.highlight pre .c1 { color: #60a0b0; font-style: italic } /* Comment.Single */ +.highlight pre .cs { color: #60a0b0; background-color: #fff0f0 } /* Comment.Special */ +.highlight pre .gd { color: #A00000 } /* Generic.Deleted */ +.highlight pre .ge { font-style: italic } /* Generic.Emph */ +.highlight pre .gr { color: #FF0000 } /* Generic.Error */ +.highlight pre .gh { color: #000080; font-weight: bold } /* Generic.Heading */ +.highlight pre .gi { color: #00A000 } /* Generic.Inserted */ +.highlight pre .go { color: #888888 } /* Generic.Output */ +.highlight pre .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */ +.highlight pre .gs { font-weight: bold } /* Generic.Strong */ +.highlight pre .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +.highlight pre .gt { color: #0044DD } /* Generic.Traceback */ +.highlight pre .kc { color: #007020; font-weight: bold } /* Keyword.Constant */ +.highlight pre .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */ +.highlight pre .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */ +.highlight pre .kp { color: #007020 } /* Keyword.Pseudo */ +.highlight pre .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */ +.highlight pre .kt { color: #902000 } /* Keyword.Type */ +.highlight pre .m { color: #40a070 } /* Literal.Number */ +.highlight pre .s { color: #4070a0 } /* Literal.String */ +.highlight pre .na { color: #4070a0 } /* Name.Attribute */ +.highlight pre .nb { color: #007020 } /* Name.Builtin */ +.highlight pre .nc { color: #0e84b5; font-weight: bold } /* Name.Class */ +.highlight pre .no { color: #60add5 } /* Name.Constant */ +.highlight pre .nd { color: #555555; font-weight: bold } /* Name.Decorator */ +.highlight pre .ni { color: #d55537; font-weight: bold } /* Name.Entity */ +.highlight pre .ne { color: #007020 } /* Name.Exception */ +.highlight pre .nf { color: #06287e } /* Name.Function */ +.highlight pre .nl { color: #002070; font-weight: bold } /* Name.Label */ +.highlight pre .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */ +.highlight pre .nt { color: #062873; font-weight: bold } /* Name.Tag */ +.highlight pre .nv { color: #bb60d5 } /* Name.Variable */ +.highlight pre .ow { color: #007020; font-weight: bold } /* Operator.Word */ +.highlight pre .w { color: #bbbbbb } /* Text.Whitespace */ +.highlight pre .mf { color: #40a070 } /* Literal.Number.Float */ +.highlight pre .mh { color: #40a070 } /* Literal.Number.Hex */ +.highlight pre .mi { color: #40a070 } /* Literal.Number.Integer */ +.highlight pre .mo { color: #40a070 } /* Literal.Number.Oct */ +.highlight pre .sb { color: #4070a0 } /* Literal.String.Backtick */ +.highlight pre .sc { color: #4070a0 } /* Literal.String.Char */ +.highlight pre .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */ +.highlight pre .s2 { color: #4070a0 } /* Literal.String.Double */ +.highlight pre .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */ +.highlight pre .sh { color: #4070a0 } /* Literal.String.Heredoc */ +.highlight pre .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */ +.highlight pre .sx { color: #c65d09 } /* Literal.String.Other */ +.highlight pre .sr { color: #235388 } /* Literal.String.Regex */ +.highlight pre .s1 { color: #4070a0 } /* Literal.String.Single */ +.highlight pre .ss { color: #517918 } /* Literal.String.Symbol */ +.highlight pre .bp { color: #007020 } /* Name.Builtin.Pseudo */ +.highlight pre .vc { color: #bb60d5 } /* Name.Variable.Class */ +.highlight pre .vg { color: #bb60d5 } /* Name.Variable.Global */ +.highlight pre .vi { color: #bb60d5 } /* Name.Variable.Instance */ +.highlight pre .il { color: #40a070 } /* Literal.Number.Integer.Long */ diff --git a/theme/css/pygments/friendly.css.gz b/theme/css/pygments/friendly.css.gz new file mode 100644 index 000000000..8514d250b Binary files /dev/null and b/theme/css/pygments/friendly.css.gz differ diff --git a/theme/css/pygments/fruity.css b/theme/css/pygments/fruity.css new file mode 100644 index 000000000..ec1fc42fe --- /dev/null +++ b/theme/css/pygments/fruity.css @@ -0,0 +1,70 @@ +.highlight pre .hll { background-color: #333333 } +.highlight pre, .highlighttable pre { background: #111111; color: #ffffff } +.highlight pre .c { color: #008800; font-style: italic; background-color: #0f140f } /* Comment */ +.highlight pre .err { color: #ffffff } /* Error */ +.highlight pre .g { color: #ffffff } /* Generic */ +.highlight pre .k { color: #fb660a; font-weight: bold } /* Keyword */ +.highlight pre .l { color: #ffffff } /* Literal */ +.highlight pre .n { color: #ffffff } /* Name */ +.highlight pre .o { color: #ffffff } /* Operator */ +.highlight pre .x { color: #ffffff } /* Other */ +.highlight pre .p { color: #ffffff } /* Punctuation */ +.highlight pre .cm { color: #008800; font-style: italic; background-color: #0f140f } /* Comment.Multiline */ +.highlight pre .cp { color: #ff0007; font-weight: bold; font-style: italic; background-color: #0f140f } /* Comment.Preproc */ +.highlight pre .c1 { color: #008800; font-style: italic; background-color: #0f140f } /* Comment.Single */ +.highlight pre .cs { color: #008800; font-style: italic; background-color: #0f140f } /* Comment.Special */ +.highlight pre .gd { color: #ffffff } /* Generic.Deleted */ +.highlight pre .ge { color: #ffffff } /* Generic.Emph */ +.highlight pre .gr { color: #ffffff } /* Generic.Error */ +.highlight pre .gh { color: #ffffff; font-weight: bold } /* Generic.Heading */ +.highlight pre .gi { color: #ffffff } /* Generic.Inserted */ +.highlight pre .go { color: #444444; background-color: #222222 } /* Generic.Output */ +.highlight pre .gp { color: #ffffff } /* Generic.Prompt */ +.highlight pre .gs { color: #ffffff } /* Generic.Strong */ +.highlight pre .gu { color: #ffffff; font-weight: bold } /* Generic.Subheading */ +.highlight pre .gt { color: #ffffff } /* Generic.Traceback */ +.highlight pre .kc { color: #fb660a; font-weight: bold } /* Keyword.Constant */ +.highlight pre .kd { color: #fb660a; font-weight: bold } /* Keyword.Declaration */ +.highlight pre .kn { color: #fb660a; font-weight: bold } /* Keyword.Namespace */ +.highlight pre .kp { color: #fb660a } /* Keyword.Pseudo */ +.highlight pre .kr { color: #fb660a; font-weight: bold } /* Keyword.Reserved */ +.highlight pre .kt { color: #cdcaa9; font-weight: bold } /* Keyword.Type */ +.highlight pre .ld { color: #ffffff } /* Literal.Date */ +.highlight pre .m { color: #0086f7; font-weight: bold } /* Literal.Number */ +.highlight pre .s { color: #0086d2 } /* Literal.String */ +.highlight pre .na { color: #ff0086; font-weight: bold } /* Name.Attribute */ +.highlight pre .nb { color: #ffffff } /* Name.Builtin */ +.highlight pre .nc { color: #ffffff } /* Name.Class */ +.highlight pre .no { color: #0086d2 } /* Name.Constant */ +.highlight pre .nd { color: #ffffff } /* Name.Decorator */ +.highlight pre .ni { color: #ffffff } /* Name.Entity */ +.highlight pre .ne { color: #ffffff } /* Name.Exception */ +.highlight pre .nf { color: #ff0086; font-weight: bold } /* Name.Function */ +.highlight pre .nl { color: #ffffff } /* Name.Label */ +.highlight pre .nn { color: #ffffff } /* Name.Namespace */ +.highlight pre .nx { color: #ffffff } /* Name.Other */ +.highlight pre .py { color: #ffffff } /* Name.Property */ +.highlight pre .nt { color: #fb660a; font-weight: bold } /* Name.Tag */ +.highlight pre .nv { color: #fb660a } /* Name.Variable */ +.highlight pre .ow { color: #ffffff } /* Operator.Word */ +.highlight pre .w { color: #888888 } /* Text.Whitespace */ +.highlight pre .mf { color: #0086f7; font-weight: bold } /* Literal.Number.Float */ +.highlight pre .mh { color: #0086f7; font-weight: bold } /* Literal.Number.Hex */ +.highlight pre .mi { color: #0086f7; font-weight: bold } /* Literal.Number.Integer */ +.highlight pre .mo { color: #0086f7; font-weight: bold } /* Literal.Number.Oct */ +.highlight pre .sb { color: #0086d2 } /* Literal.String.Backtick */ +.highlight pre .sc { color: #0086d2 } /* Literal.String.Char */ +.highlight pre .sd { color: #0086d2 } /* Literal.String.Doc */ +.highlight pre .s2 { color: #0086d2 } /* Literal.String.Double */ +.highlight pre .se { color: #0086d2 } /* Literal.String.Escape */ +.highlight pre .sh { color: #0086d2 } /* Literal.String.Heredoc */ +.highlight pre .si { color: #0086d2 } /* Literal.String.Interpol */ +.highlight pre .sx { color: #0086d2 } /* Literal.String.Other */ +.highlight pre .sr { color: #0086d2 } /* Literal.String.Regex */ +.highlight pre .s1 { color: #0086d2 } /* Literal.String.Single */ +.highlight pre .ss { color: #0086d2 } /* Literal.String.Symbol */ +.highlight pre .bp { color: #ffffff } /* Name.Builtin.Pseudo */ +.highlight pre .vc { color: #fb660a } /* Name.Variable.Class */ +.highlight pre .vg { color: #fb660a } /* Name.Variable.Global */ +.highlight pre .vi { color: #fb660a } /* Name.Variable.Instance */ +.highlight pre .il { color: #0086f7; font-weight: bold } /* Literal.Number.Integer.Long */ diff --git a/theme/css/pygments/fruity.css.gz b/theme/css/pygments/fruity.css.gz new file mode 100644 index 000000000..5535db0ed Binary files /dev/null and b/theme/css/pygments/fruity.css.gz differ diff --git a/theme/css/pygments/manni.css b/theme/css/pygments/manni.css new file mode 100644 index 000000000..a5dbc2af7 --- /dev/null +++ b/theme/css/pygments/manni.css @@ -0,0 +1,62 @@ +.highlight pre .hll { background-color: #ffffcc } +.highlight pre, .highlighttable pre { background: #f0f3f3; } +.highlight pre .c { color: #0099FF; font-style: italic } /* Comment */ +.highlight pre .err { color: #AA0000; background-color: #FFAAAA } /* Error */ +.highlight pre .k { color: #006699; font-weight: bold } /* Keyword */ +.highlight pre .o { color: #555555 } /* Operator */ +.highlight pre .cm { color: #0099FF; font-style: italic } /* Comment.Multiline */ +.highlight pre .cp { color: #009999 } /* Comment.Preproc */ +.highlight pre .c1 { color: #0099FF; font-style: italic } /* Comment.Single */ +.highlight pre .cs { color: #0099FF; font-weight: bold; font-style: italic } /* Comment.Special */ +.highlight pre .gd { background-color: #FFCCCC; border: 1px solid #CC0000 } /* Generic.Deleted */ +.highlight pre .ge { font-style: italic } /* Generic.Emph */ +.highlight pre .gr { color: #FF0000 } /* Generic.Error */ +.highlight pre .gh { color: #003300; font-weight: bold } /* Generic.Heading */ +.highlight pre .gi { background-color: #CCFFCC; border: 1px solid #00CC00 } /* Generic.Inserted */ +.highlight pre .go { color: #AAAAAA } /* Generic.Output */ +.highlight pre .gp { color: #000099; font-weight: bold } /* Generic.Prompt */ +.highlight pre .gs { font-weight: bold } /* Generic.Strong */ +.highlight pre .gu { color: #003300; font-weight: bold } /* Generic.Subheading */ +.highlight pre .gt { color: #99CC66 } /* Generic.Traceback */ +.highlight pre .kc { color: #006699; font-weight: bold } /* Keyword.Constant */ +.highlight pre .kd { color: #006699; font-weight: bold } /* Keyword.Declaration */ +.highlight pre .kn { color: #006699; font-weight: bold } /* Keyword.Namespace */ +.highlight pre .kp { color: #006699 } /* Keyword.Pseudo */ +.highlight pre .kr { color: #006699; font-weight: bold } /* Keyword.Reserved */ +.highlight pre .kt { color: #007788; font-weight: bold } /* Keyword.Type */ +.highlight pre .m { color: #FF6600 } /* Literal.Number */ +.highlight pre .s { color: #CC3300 } /* Literal.String */ +.highlight pre .na { color: #330099 } /* Name.Attribute */ +.highlight pre .nb { color: #336666 } /* Name.Builtin */ +.highlight pre .nc { color: #00AA88; font-weight: bold } /* Name.Class */ +.highlight pre .no { color: #336600 } /* Name.Constant */ +.highlight pre .nd { color: #9999FF } /* Name.Decorator */ +.highlight pre .ni { color: #999999; font-weight: bold } /* Name.Entity */ +.highlight pre .ne { color: #CC0000; font-weight: bold } /* Name.Exception */ +.highlight pre .nf { color: #CC00FF } /* Name.Function */ +.highlight pre .nl { color: #9999FF } /* Name.Label */ +.highlight pre .nn { color: #00CCFF; font-weight: bold } /* Name.Namespace */ +.highlight pre .nt { color: #330099; font-weight: bold } /* Name.Tag */ +.highlight pre .nv { color: #003333 } /* Name.Variable */ +.highlight pre .ow { color: #000000; font-weight: bold } /* Operator.Word */ +.highlight pre .w { color: #bbbbbb } /* Text.Whitespace */ +.highlight pre .mf { color: #FF6600 } /* Literal.Number.Float */ +.highlight pre .mh { color: #FF6600 } /* Literal.Number.Hex */ +.highlight pre .mi { color: #FF6600 } /* Literal.Number.Integer */ +.highlight pre .mo { color: #FF6600 } /* Literal.Number.Oct */ +.highlight pre .sb { color: #CC3300 } /* Literal.String.Backtick */ +.highlight pre .sc { color: #CC3300 } /* Literal.String.Char */ +.highlight pre .sd { color: #CC3300; font-style: italic } /* Literal.String.Doc */ +.highlight pre .s2 { color: #CC3300 } /* Literal.String.Double */ +.highlight pre .se { color: #CC3300; font-weight: bold } /* Literal.String.Escape */ +.highlight pre .sh { color: #CC3300 } /* Literal.String.Heredoc */ +.highlight pre .si { color: #AA0000 } /* Literal.String.Interpol */ +.highlight pre .sx { color: #CC3300 } /* Literal.String.Other */ +.highlight pre .sr { color: #33AAAA } /* Literal.String.Regex */ +.highlight pre .s1 { color: #CC3300 } /* Literal.String.Single */ +.highlight pre .ss { color: #FFCC33 } /* Literal.String.Symbol */ +.highlight pre .bp { color: #336666 } /* Name.Builtin.Pseudo */ +.highlight pre .vc { color: #003333 } /* Name.Variable.Class */ +.highlight pre .vg { color: #003333 } /* Name.Variable.Global */ +.highlight pre .vi { color: #003333 } /* Name.Variable.Instance */ +.highlight pre .il { color: #FF6600 } /* Literal.Number.Integer.Long */ diff --git a/theme/css/pygments/manni.css.gz b/theme/css/pygments/manni.css.gz new file mode 100644 index 000000000..8358ce2bc Binary files /dev/null and b/theme/css/pygments/manni.css.gz differ diff --git a/theme/css/pygments/monokai.css b/theme/css/pygments/monokai.css new file mode 100644 index 000000000..0db9ceaca --- /dev/null +++ b/theme/css/pygments/monokai.css @@ -0,0 +1,60 @@ +.highlight pre .hll { background-color: #49483e } +.highlight pre, .highlighttable pre { background: #272822; color: #f8f8f2 } +.highlight pre .c { color: #75715e } /* Comment */ +.highlight pre .err { color: #960050; background-color: #1e0010 } /* Error */ +.highlight pre .k { color: #66d9ef } /* Keyword */ +.highlight pre .l { color: #ae81ff } /* Literal */ +.highlight pre .n { color: #f8f8f2 } /* Name */ +.highlight pre .o { color: #f92672 } /* Operator */ +.highlight pre .p { color: #f8f8f2 } /* Punctuation */ +.highlight pre .cm { color: #75715e } /* Comment.Multiline */ +.highlight pre .cp { color: #75715e } /* Comment.Preproc */ +.highlight pre .c1 { color: #75715e } /* Comment.Single */ +.highlight pre .cs { color: #75715e } /* Comment.Special */ +.highlight pre .ge { font-style: italic } /* Generic.Emph */ +.highlight pre .gs { font-weight: bold } /* Generic.Strong */ +.highlight pre .kc { color: #66d9ef } /* Keyword.Constant */ +.highlight pre .kd { color: #66d9ef } /* Keyword.Declaration */ +.highlight pre .kn { color: #f92672 } /* Keyword.Namespace */ +.highlight pre .kp { color: #66d9ef } /* Keyword.Pseudo */ +.highlight pre .kr { color: #66d9ef } /* Keyword.Reserved */ +.highlight pre .kt { color: #66d9ef } /* Keyword.Type */ +.highlight pre .ld { color: #e6db74 } /* Literal.Date */ +.highlight pre .m { color: #ae81ff } /* Literal.Number */ +.highlight pre .s { color: #e6db74 } /* Literal.String */ +.highlight pre .na { color: #a6e22e } /* Name.Attribute */ +.highlight pre .nb { color: #f8f8f2 } /* Name.Builtin */ +.highlight pre .nc { color: #a6e22e } /* Name.Class */ +.highlight pre .no { color: #66d9ef } /* Name.Constant */ +.highlight pre .nd { color: #a6e22e } /* Name.Decorator */ +.highlight pre .ni { color: #f8f8f2 } /* Name.Entity */ +.highlight pre .ne { color: #a6e22e } /* Name.Exception */ +.highlight pre .nf { color: #a6e22e } /* Name.Function */ +.highlight pre .nl { color: #f8f8f2 } /* Name.Label */ +.highlight pre .nn { color: #f8f8f2 } /* Name.Namespace */ +.highlight pre .nx { color: #a6e22e } /* Name.Other */ +.highlight pre .py { color: #f8f8f2 } /* Name.Property */ +.highlight pre .nt { color: #f92672 } /* Name.Tag */ +.highlight pre .nv { color: #f8f8f2 } /* Name.Variable */ +.highlight pre .ow { color: #f92672 } /* Operator.Word */ +.highlight pre .w { color: #f8f8f2 } /* Text.Whitespace */ +.highlight pre .mf { color: #ae81ff } /* Literal.Number.Float */ +.highlight pre .mh { color: #ae81ff } /* Literal.Number.Hex */ +.highlight pre .mi { color: #ae81ff } /* Literal.Number.Integer */ +.highlight pre .mo { color: #ae81ff } /* Literal.Number.Oct */ +.highlight pre .sb { color: #e6db74 } /* Literal.String.Backtick */ +.highlight pre .sc { color: #e6db74 } /* Literal.String.Char */ +.highlight pre .sd { color: #e6db74 } /* Literal.String.Doc */ +.highlight pre .s2 { color: #e6db74 } /* Literal.String.Double */ +.highlight pre .se { color: #ae81ff } /* Literal.String.Escape */ +.highlight pre .sh { color: #e6db74 } /* Literal.String.Heredoc */ +.highlight pre .si { color: #e6db74 } /* Literal.String.Interpol */ +.highlight pre .sx { color: #e6db74 } /* Literal.String.Other */ +.highlight pre .sr { color: #e6db74 } /* Literal.String.Regex */ +.highlight pre .s1 { color: #e6db74 } /* Literal.String.Single */ +.highlight pre .ss { color: #e6db74 } /* Literal.String.Symbol */ +.highlight pre .bp { color: #f8f8f2 } /* Name.Builtin.Pseudo */ +.highlight pre .vc { color: #f8f8f2 } /* Name.Variable.Class */ +.highlight pre .vg { color: #f8f8f2 } /* Name.Variable.Global */ +.highlight pre .vi { color: #f8f8f2 } /* Name.Variable.Instance */ +.highlight pre .il { color: #ae81ff } /* Literal.Number.Integer.Long */ diff --git a/theme/css/pygments/monokai.css.gz b/theme/css/pygments/monokai.css.gz new file mode 100644 index 000000000..17e029149 Binary files /dev/null and b/theme/css/pygments/monokai.css.gz differ diff --git a/theme/css/pygments/murphy.css b/theme/css/pygments/murphy.css new file mode 100644 index 000000000..085431a24 --- /dev/null +++ b/theme/css/pygments/murphy.css @@ -0,0 +1,62 @@ +.highlight pre .hll { background-color: #ffffcc } +.highlight pre, .highlighttable pre { background: #ffffff; } +.highlight pre .c { color: #666666; font-style: italic } /* Comment */ +.highlight pre .err { color: #FF0000; background-color: #FFAAAA } /* Error */ +.highlight pre .k { color: #228899; font-weight: bold } /* Keyword */ +.highlight pre .o { color: #333333 } /* Operator */ +.highlight pre .cm { color: #666666; font-style: italic } /* Comment.Multiline */ +.highlight pre .cp { color: #557799 } /* Comment.Preproc */ +.highlight pre .c1 { color: #666666; font-style: italic } /* Comment.Single */ +.highlight pre .cs { color: #cc0000; font-weight: bold; font-style: italic } /* Comment.Special */ +.highlight pre .gd { color: #A00000 } /* Generic.Deleted */ +.highlight pre .ge { font-style: italic } /* Generic.Emph */ +.highlight pre .gr { color: #FF0000 } /* Generic.Error */ +.highlight pre .gh { color: #000080; font-weight: bold } /* Generic.Heading */ +.highlight pre .gi { color: #00A000 } /* Generic.Inserted */ +.highlight pre .go { color: #888888 } /* Generic.Output */ +.highlight pre .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */ +.highlight pre .gs { font-weight: bold } /* Generic.Strong */ +.highlight pre .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +.highlight pre .gt { color: #0044DD } /* Generic.Traceback */ +.highlight pre .kc { color: #228899; font-weight: bold } /* Keyword.Constant */ +.highlight pre .kd { color: #228899; font-weight: bold } /* Keyword.Declaration */ +.highlight pre .kn { color: #228899; font-weight: bold } /* Keyword.Namespace */ +.highlight pre .kp { color: #0088ff; font-weight: bold } /* Keyword.Pseudo */ +.highlight pre .kr { color: #228899; font-weight: bold } /* Keyword.Reserved */ +.highlight pre .kt { color: #6666ff; font-weight: bold } /* Keyword.Type */ +.highlight pre .m { color: #6600EE; font-weight: bold } /* Literal.Number */ +.highlight pre .s { background-color: #e0e0ff } /* Literal.String */ +.highlight pre .na { color: #000077 } /* Name.Attribute */ +.highlight pre .nb { color: #007722 } /* Name.Builtin */ +.highlight pre .nc { color: #ee99ee; font-weight: bold } /* Name.Class */ +.highlight pre .no { color: #55eedd; font-weight: bold } /* Name.Constant */ +.highlight pre .nd { color: #555555; font-weight: bold } /* Name.Decorator */ +.highlight pre .ni { color: #880000 } /* Name.Entity */ +.highlight pre .ne { color: #FF0000; font-weight: bold } /* Name.Exception */ +.highlight pre .nf { color: #55eedd; font-weight: bold } /* Name.Function */ +.highlight pre .nl { color: #997700; font-weight: bold } /* Name.Label */ +.highlight pre .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */ +.highlight pre .nt { color: #007700 } /* Name.Tag */ +.highlight pre .nv { color: #003366 } /* Name.Variable */ +.highlight pre .ow { color: #000000; font-weight: bold } /* Operator.Word */ +.highlight pre .w { color: #bbbbbb } /* Text.Whitespace */ +.highlight pre .mf { color: #6600EE; font-weight: bold } /* Literal.Number.Float */ +.highlight pre .mh { color: #005588; font-weight: bold } /* Literal.Number.Hex */ +.highlight pre .mi { color: #6666ff; font-weight: bold } /* Literal.Number.Integer */ +.highlight pre .mo { color: #4400EE; font-weight: bold } /* Literal.Number.Oct */ +.highlight pre .sb { background-color: #e0e0ff } /* Literal.String.Backtick */ +.highlight pre .sc { color: #8888FF } /* Literal.String.Char */ +.highlight pre .sd { color: #DD4422 } /* Literal.String.Doc */ +.highlight pre .s2 { background-color: #e0e0ff } /* Literal.String.Double */ +.highlight pre .se { color: #666666; font-weight: bold; background-color: #e0e0ff } /* Literal.String.Escape */ +.highlight pre .sh { background-color: #e0e0ff } /* Literal.String.Heredoc */ +.highlight pre .si { background-color: #eeeeee } /* Literal.String.Interpol */ +.highlight pre .sx { color: #ff8888; background-color: #e0e0ff } /* Literal.String.Other */ +.highlight pre .sr { color: #000000; background-color: #e0e0ff } /* Literal.String.Regex */ +.highlight pre .s1 { background-color: #e0e0ff } /* Literal.String.Single */ +.highlight pre .ss { color: #ffcc88 } /* Literal.String.Symbol */ +.highlight pre .bp { color: #007722 } /* Name.Builtin.Pseudo */ +.highlight pre .vc { color: #ccccff } /* Name.Variable.Class */ +.highlight pre .vg { color: #ff8844 } /* Name.Variable.Global */ +.highlight pre .vi { color: #aaaaff } /* Name.Variable.Instance */ +.highlight pre .il { color: #6666ff; font-weight: bold } /* Literal.Number.Integer.Long */ diff --git a/theme/css/pygments/murphy.css.gz b/theme/css/pygments/murphy.css.gz new file mode 100644 index 000000000..888896d9d Binary files /dev/null and b/theme/css/pygments/murphy.css.gz differ diff --git a/theme/css/pygments/native.css b/theme/css/pygments/native.css new file mode 100644 index 000000000..03b9f830e --- /dev/null +++ b/theme/css/pygments/native.css @@ -0,0 +1 @@ +.highlight pre .hll{background-color:#404040}.highlight pre,.highlighttable pre{background:#202020;color:#d0d0d0}.highlight pre .c{color:#999999;font-style:italic}.highlight pre .err{color:#a61717;background-color:#e3d2d2}.highlight pre .g{color:#d0d0d0}.highlight pre .k{color:#6ab825;font-weight:bold}.highlight pre .l{color:#d0d0d0}.highlight pre .n{color:#d0d0d0}.highlight pre .o{color:#d0d0d0}.highlight pre .x{color:#d0d0d0}.highlight pre .p{color:#d0d0d0}.highlight pre .cm{color:#999999;font-style:italic}.highlight pre .cp{color:#cd2828;font-weight:bold}.highlight pre .c1{color:#999999;font-style:italic}.highlight pre .cs{color:#e50808;font-weight:bold;background-color:#520000}.highlight pre .gd{color:#d22323}.highlight pre .ge{color:#d0d0d0;font-style:italic}.highlight pre .gr{color:#d22323}.highlight pre .gh{color:#ffffff;font-weight:bold}.highlight pre .gi{color:#589819}.highlight pre .go{color:#cccccc}.highlight pre .gp{color:#aaaaaa}.highlight pre .gs{color:#d0d0d0;font-weight:bold}.highlight pre .gu{color:#ffffff;text-decoration:underline}.highlight pre .gt{color:#d22323}.highlight pre .kc{color:#6ab825;font-weight:bold}.highlight pre .kd{color:#6ab825;font-weight:bold}.highlight pre .kn{color:#6ab825;font-weight:bold}.highlight pre .kp{color:#6ab825}.highlight pre .kr{color:#6ab825;font-weight:bold}.highlight pre .kt{color:#6ab825;font-weight:bold}.highlight pre .ld{color:#d0d0d0}.highlight pre .m{color:#3677a9}.highlight pre .s{color:#ed9d13}.highlight pre .na{color:#bbbbbb}.highlight pre .nb{color:#24909d}.highlight pre .nc{color:#447fcf;text-decoration:underline}.highlight pre .no{color:#40ffff}.highlight pre .nd{color:#ffa500}.highlight pre .ni{color:#d0d0d0}.highlight pre .ne{color:#bbbbbb}.highlight pre .nf{color:#447fcf}.highlight pre .nl{color:#d0d0d0}.highlight pre .nn{color:#447fcf;text-decoration:underline}.highlight pre .nx{color:#d0d0d0}.highlight pre .py{color:#d0d0d0}.highlight pre .nt{color:#6ab825;font-weight:bold}.highlight pre .nv{color:#40ffff}.highlight pre .ow{color:#6ab825;font-weight:bold}.highlight pre .w{color:#666666}.highlight pre .mf{color:#3677a9}.highlight pre .mh{color:#3677a9}.highlight pre .mi{color:#3677a9}.highlight pre .mo{color:#3677a9}.highlight pre .sb{color:#ed9d13}.highlight pre .sc{color:#ed9d13}.highlight pre .sd{color:#ed9d13}.highlight pre .s2{color:#ed9d13}.highlight pre .se{color:#ed9d13}.highlight pre .sh{color:#ed9d13}.highlight pre .si{color:#ed9d13}.highlight pre .sx{color:#ffa500}.highlight pre .sr{color:#ed9d13}.highlight pre .s1{color:#ed9d13}.highlight pre .ss{color:#ed9d13}.highlight pre .bp{color:#24909d}.highlight pre .vc{color:#40ffff}.highlight pre .vg{color:#40ffff}.highlight pre .vi{color:#40ffff}.highlight pre .il{color:#3677a9} \ No newline at end of file diff --git a/theme/css/pygments/native.css.gz b/theme/css/pygments/native.css.gz new file mode 100644 index 000000000..6350f151f Binary files /dev/null and b/theme/css/pygments/native.css.gz differ diff --git a/theme/css/pygments/pastie.css b/theme/css/pygments/pastie.css new file mode 100644 index 000000000..e26a684eb --- /dev/null +++ b/theme/css/pygments/pastie.css @@ -0,0 +1,61 @@ +.highlight pre .hll { background-color: #ffffcc } +.highlight pre, .highlighttable pre { background: #ffffff; } +.highlight pre .c { color: #888888 } /* Comment */ +.highlight pre .err { color: #a61717; background-color: #e3d2d2 } /* Error */ +.highlight pre .k { color: #008800; font-weight: bold } /* Keyword */ +.highlight pre .cm { color: #888888 } /* Comment.Multiline */ +.highlight pre .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */ +.highlight pre .c1 { color: #888888 } /* Comment.Single */ +.highlight pre .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */ +.highlight pre .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ +.highlight pre .ge { font-style: italic } /* Generic.Emph */ +.highlight pre .gr { color: #aa0000 } /* Generic.Error */ +.highlight pre .gh { color: #333333 } /* Generic.Heading */ +.highlight pre .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ +.highlight pre .go { color: #888888 } /* Generic.Output */ +.highlight pre .gp { color: #555555 } /* Generic.Prompt */ +.highlight pre .gs { font-weight: bold } /* Generic.Strong */ +.highlight pre .gu { color: #666666 } /* Generic.Subheading */ +.highlight pre .gt { color: #aa0000 } /* Generic.Traceback */ +.highlight pre .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ +.highlight pre .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ +.highlight pre .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ +.highlight pre .kp { color: #008800 } /* Keyword.Pseudo */ +.highlight pre .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ +.highlight pre .kt { color: #888888; font-weight: bold } /* Keyword.Type */ +.highlight pre .m { color: #0000DD; font-weight: bold } /* Literal.Number */ +.highlight pre .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ +.highlight pre .na { color: #336699 } /* Name.Attribute */ +.highlight pre .nb { color: #003388 } /* Name.Builtin */ +.highlight pre .nc { color: #bb0066; font-weight: bold } /* Name.Class */ +.highlight pre .no { color: #003366; font-weight: bold } /* Name.Constant */ +.highlight pre .nd { color: #555555 } /* Name.Decorator */ +.highlight pre .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ +.highlight pre .nf { color: #0066bb; font-weight: bold } /* Name.Function */ +.highlight pre .nl { color: #336699; font-style: italic } /* Name.Label */ +.highlight pre .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ +.highlight pre .py { color: #336699; font-weight: bold } /* Name.Property */ +.highlight pre .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ +.highlight pre .nv { color: #336699 } /* Name.Variable */ +.highlight pre .ow { color: #008800 } /* Operator.Word */ +.highlight pre .w { color: #bbbbbb } /* Text.Whitespace */ +.highlight pre .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ +.highlight pre .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ +.highlight pre .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ +.highlight pre .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ +.highlight pre .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ +.highlight pre .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ +.highlight pre .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ +.highlight pre .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ +.highlight pre .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ +.highlight pre .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ +.highlight pre .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ +.highlight pre .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ +.highlight pre .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ +.highlight pre .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ +.highlight pre .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ +.highlight pre .bp { color: #003388 } /* Name.Builtin.Pseudo */ +.highlight pre .vc { color: #336699 } /* Name.Variable.Class */ +.highlight pre .vg { color: #dd7700 } /* Name.Variable.Global */ +.highlight pre .vi { color: #3333bb } /* Name.Variable.Instance */ +.highlight pre .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */ diff --git a/theme/css/pygments/pastie.css.gz b/theme/css/pygments/pastie.css.gz new file mode 100644 index 000000000..cf7e9b86d Binary files /dev/null and b/theme/css/pygments/pastie.css.gz differ diff --git a/theme/css/pygments/perldoc.css b/theme/css/pygments/perldoc.css new file mode 100644 index 000000000..1121f7366 --- /dev/null +++ b/theme/css/pygments/perldoc.css @@ -0,0 +1,59 @@ +.highlight pre .hll { background-color: #ffffcc } +.highlight pre, .highlighttable pre { background: #eeeedd; } +.highlight pre .c { color: #228B22 } /* Comment */ +.highlight pre .err { color: #a61717; background-color: #e3d2d2 } /* Error */ +.highlight pre .k { color: #8B008B; font-weight: bold } /* Keyword */ +.highlight pre .cm { color: #228B22 } /* Comment.Multiline */ +.highlight pre .cp { color: #1e889b } /* Comment.Preproc */ +.highlight pre .c1 { color: #228B22 } /* Comment.Single */ +.highlight pre .cs { color: #8B008B; font-weight: bold } /* Comment.Special */ +.highlight pre .gd { color: #aa0000 } /* Generic.Deleted */ +.highlight pre .ge { font-style: italic } /* Generic.Emph */ +.highlight pre .gr { color: #aa0000 } /* Generic.Error */ +.highlight pre .gh { color: #000080; font-weight: bold } /* Generic.Heading */ +.highlight pre .gi { color: #00aa00 } /* Generic.Inserted */ +.highlight pre .go { color: #888888 } /* Generic.Output */ +.highlight pre .gp { color: #555555 } /* Generic.Prompt */ +.highlight pre .gs { font-weight: bold } /* Generic.Strong */ +.highlight pre .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +.highlight pre .gt { color: #aa0000 } /* Generic.Traceback */ +.highlight pre .kc { color: #8B008B; font-weight: bold } /* Keyword.Constant */ +.highlight pre .kd { color: #8B008B; font-weight: bold } /* Keyword.Declaration */ +.highlight pre .kn { color: #8B008B; font-weight: bold } /* Keyword.Namespace */ +.highlight pre .kp { color: #8B008B; font-weight: bold } /* Keyword.Pseudo */ +.highlight pre .kr { color: #8B008B; font-weight: bold } /* Keyword.Reserved */ +.highlight pre .kt { color: #a7a7a7; font-weight: bold } /* Keyword.Type */ +.highlight pre .m { color: #B452CD } /* Literal.Number */ +.highlight pre .s { color: #CD5555 } /* Literal.String */ +.highlight pre .na { color: #658b00 } /* Name.Attribute */ +.highlight pre .nb { color: #658b00 } /* Name.Builtin */ +.highlight pre .nc { color: #008b45; font-weight: bold } /* Name.Class */ +.highlight pre .no { color: #00688B } /* Name.Constant */ +.highlight pre .nd { color: #707a7c } /* Name.Decorator */ +.highlight pre .ne { color: #008b45; font-weight: bold } /* Name.Exception */ +.highlight pre .nf { color: #008b45 } /* Name.Function */ +.highlight pre .nn { color: #008b45; text-decoration: underline } /* Name.Namespace */ +.highlight pre .nt { color: #8B008B; font-weight: bold } /* Name.Tag */ +.highlight pre .nv { color: #00688B } /* Name.Variable */ +.highlight pre .ow { color: #8B008B } /* Operator.Word */ +.highlight pre .w { color: #bbbbbb } /* Text.Whitespace */ +.highlight pre .mf { color: #B452CD } /* Literal.Number.Float */ +.highlight pre .mh { color: #B452CD } /* Literal.Number.Hex */ +.highlight pre .mi { color: #B452CD } /* Literal.Number.Integer */ +.highlight pre .mo { color: #B452CD } /* Literal.Number.Oct */ +.highlight pre .sb { color: #CD5555 } /* Literal.String.Backtick */ +.highlight pre .sc { color: #CD5555 } /* Literal.String.Char */ +.highlight pre .sd { color: #CD5555 } /* Literal.String.Doc */ +.highlight pre .s2 { color: #CD5555 } /* Literal.String.Double */ +.highlight pre .se { color: #CD5555 } /* Literal.String.Escape */ +.highlight pre .sh { color: #1c7e71; font-style: italic } /* Literal.String.Heredoc */ +.highlight pre .si { color: #CD5555 } /* Literal.String.Interpol */ +.highlight pre .sx { color: #cb6c20 } /* Literal.String.Other */ +.highlight pre .sr { color: #1c7e71 } /* Literal.String.Regex */ +.highlight pre .s1 { color: #CD5555 } /* Literal.String.Single */ +.highlight pre .ss { color: #CD5555 } /* Literal.String.Symbol */ +.highlight pre .bp { color: #658b00 } /* Name.Builtin.Pseudo */ +.highlight pre .vc { color: #00688B } /* Name.Variable.Class */ +.highlight pre .vg { color: #00688B } /* Name.Variable.Global */ +.highlight pre .vi { color: #00688B } /* Name.Variable.Instance */ +.highlight pre .il { color: #B452CD } /* Literal.Number.Integer.Long */ diff --git a/theme/css/pygments/perldoc.css.gz b/theme/css/pygments/perldoc.css.gz new file mode 100644 index 000000000..c2dd22883 Binary files /dev/null and b/theme/css/pygments/perldoc.css.gz differ diff --git a/theme/css/pygments/solarizeddark.css b/theme/css/pygments/solarizeddark.css new file mode 100644 index 000000000..27e281f38 --- /dev/null +++ b/theme/css/pygments/solarizeddark.css @@ -0,0 +1,70 @@ +.highlight pre .hll { background-color: #ffffcc } +.highlight pre, .highlighttable pre { background: #002b36; color: #839496 } +.highlight pre .c { color: #586e75; font-style: italic } /* Comment */ +.highlight pre .err { color: #dc322f } /* Error */ +.highlight pre .g { color: #839496 } /* Generic */ +.highlight pre .k { color: #859900 } /* Keyword */ +.highlight pre .l { color: #839496 } /* Literal */ +.highlight pre .n { color: #93a1a1 } /* Name */ +.highlight pre .o { color: #839496 } /* Operator */ +.highlight pre .x { color: #839496 } /* Other */ +.highlight pre .p { color: #839496 } /* Punctuation */ +.highlight pre .cm { color: #586e75; font-style: italic } /* Comment.Multiline */ +.highlight pre .cp { color: #586e75; font-style: italic } /* Comment.Preproc */ +.highlight pre .c1 { color: #586e75; font-style: italic } /* Comment.Single */ +.highlight pre .cs { color: #586e75; font-style: italic } /* Comment.Special */ +.highlight pre .gd { color: #839496 } /* Generic.Deleted */ +.highlight pre .ge { color: #839496 } /* Generic.Emph */ +.highlight pre .gr { color: #839496 } /* Generic.Error */ +.highlight pre .gh { color: #839496 } /* Generic.Heading */ +.highlight pre .gi { color: #839496 } /* Generic.Inserted */ +.highlight pre .go { color: #839496 } /* Generic.Output */ +.highlight pre .gp { color: #839496 } /* Generic.Prompt */ +.highlight pre .gs { color: #839496 } /* Generic.Strong */ +.highlight pre .gu { color: #839496 } /* Generic.Subheading */ +.highlight pre .gt { color: #839496 } /* Generic.Traceback */ +.highlight pre .kc { color: #859900 } /* Keyword.Constant */ +.highlight pre .kd { color: #859900 } /* Keyword.Declaration */ +.highlight pre .kn { color: #cb4b16 } /* Keyword.Namespace */ +.highlight pre .kp { color: #cb4b16 } /* Keyword.Pseudo */ +.highlight pre .kr { color: #859900 } /* Keyword.Reserved */ +.highlight pre .kt { color: #859900 } /* Keyword.Type */ +.highlight pre .ld { color: #839496 } /* Literal.Date */ +.highlight pre .m { color: #2aa198 } /* Literal.Number */ +.highlight pre .s { color: #2aa198 } /* Literal.String */ +.highlight pre .na { color: #839496 } /* Name.Attribute */ +.highlight pre .nb { color: #268bd2 } /* Name.Builtin */ +.highlight pre .nc { color: #268bd2 } /* Name.Class */ +.highlight pre .no { color: #b58900 } /* Name.Constant */ +.highlight pre .nd { color: #cb4b16 } /* Name.Decorator */ +.highlight pre .ni { color: #cb4b16 } /* Name.Entity */ +.highlight pre .ne { color: #cb4b16 } /* Name.Exception */ +.highlight pre .nf { color: #268bd2 } /* Name.Function */ +.highlight pre .nl { color: #839496 } /* Name.Label */ +.highlight pre .nn { color: #b58900 } /* Name.Namespace */ +.highlight pre .nx { color: #839496 } /* Name.Other */ +.highlight pre .py { color: #268bd2 } /* Name.Property */ +.highlight pre .nt { color: #859900 } /* Name.Tag */ +.highlight pre .nv { color: #cb4b16 } /* Name.Variable */ +.highlight pre .ow { color: #859900 } /* Operator.Word */ +.highlight pre .w { color: #002b36 } /* Text.Whitespace */ +.highlight pre .mf { color: #2aa198 } /* Literal.Number.Float */ +.highlight pre .mh { color: #2aa198 } /* Literal.Number.Hex */ +.highlight pre .mi { color: #2aa198 } /* Literal.Number.Integer */ +.highlight pre .mo { color: #2aa198 } /* Literal.Number.Oct */ +.highlight pre .sb { color: #2aa198 } /* Literal.String.Backtick */ +.highlight pre .sc { color: #2aa198 } /* Literal.String.Char */ +.highlight pre .sd { color: #2aa198 } /* Literal.String.Doc */ +.highlight pre .s2 { color: #2aa198 } /* Literal.String.Double */ +.highlight pre .se { color: #cb4b16 } /* Literal.String.Escape */ +.highlight pre .sh { color: #2aa198 } /* Literal.String.Heredoc */ +.highlight pre .si { color: #cb4b16 } /* Literal.String.Interpol */ +.highlight pre .sx { color: #2aa198 } /* Literal.String.Other */ +.highlight pre .sr { color: #2aa198 } /* Literal.String.Regex */ +.highlight pre .s1 { color: #2aa198 } /* Literal.String.Single */ +.highlight pre .ss { color: #2aa198 } /* Literal.String.Symbol */ +.highlight pre .bp { color: #268bd2; font-weight: bold } /* Name.Builtin.Pseudo */ +.highlight pre .vc { color: #268bd2 } /* Name.Variable.Class */ +.highlight pre .vg { color: #268bd2 } /* Name.Variable.Global */ +.highlight pre .vi { color: #268bd2 } /* Name.Variable.Instance */ +.highlight pre .il { color: #2aa198 } /* Literal.Number.Integer.Long */ diff --git a/theme/css/pygments/solarizeddark.css.gz b/theme/css/pygments/solarizeddark.css.gz new file mode 100644 index 000000000..558ad4a7a Binary files /dev/null and b/theme/css/pygments/solarizeddark.css.gz differ diff --git a/theme/css/pygments/solarizedlight.css b/theme/css/pygments/solarizedlight.css new file mode 100644 index 000000000..9c0dc8ef5 --- /dev/null +++ b/theme/css/pygments/solarizedlight.css @@ -0,0 +1,70 @@ +.highlight pre .hll { background-color: #ffffcc } +.highlight pre, .highlighttable pre { background: #fdf6e3; color: #657b83 } +.highlight pre .c { color: #93a1a1; font-style: italic } /* Comment */ +.highlight pre .err { color: #dc322f } /* Error */ +.highlight pre .g { color: #657b83 } /* Generic */ +.highlight pre .k { color: #859900 } /* Keyword */ +.highlight pre .l { color: #657b83 } /* Literal */ +.highlight pre .n { color: #586e75 } /* Name */ +.highlight pre .o { color: #657b83 } /* Operator */ +.highlight pre .x { color: #657b83 } /* Other */ +.highlight pre .p { color: #657b83 } /* Punctuation */ +.highlight pre .cm { color: #93a1a1; font-style: italic } /* Comment.Multiline */ +.highlight pre .cp { color: #93a1a1; font-style: italic } /* Comment.Preproc */ +.highlight pre .c1 { color: #93a1a1; font-style: italic } /* Comment.Single */ +.highlight pre .cs { color: #93a1a1; font-style: italic } /* Comment.Special */ +.highlight pre .gd { color: #657b83 } /* Generic.Deleted */ +.highlight pre .ge { color: #657b83 } /* Generic.Emph */ +.highlight pre .gr { color: #657b83 } /* Generic.Error */ +.highlight pre .gh { color: #657b83 } /* Generic.Heading */ +.highlight pre .gi { color: #657b83 } /* Generic.Inserted */ +.highlight pre .go { color: #657b83 } /* Generic.Output */ +.highlight pre .gp { color: #657b83 } /* Generic.Prompt */ +.highlight pre .gs { color: #657b83 } /* Generic.Strong */ +.highlight pre .gu { color: #657b83 } /* Generic.Subheading */ +.highlight pre .gt { color: #657b83 } /* Generic.Traceback */ +.highlight pre .kc { color: #859900 } /* Keyword.Constant */ +.highlight pre .kd { color: #859900 } /* Keyword.Declaration */ +.highlight pre .kn { color: #cb4b16 } /* Keyword.Namespace */ +.highlight pre .kp { color: #cb4b16 } /* Keyword.Pseudo */ +.highlight pre .kr { color: #859900 } /* Keyword.Reserved */ +.highlight pre .kt { color: #859900 } /* Keyword.Type */ +.highlight pre .ld { color: #657b83 } /* Literal.Date */ +.highlight pre .m { color: #2aa198 } /* Literal.Number */ +.highlight pre .s { color: #2aa198 } /* Literal.String */ +.highlight pre .na { color: #657b83 } /* Name.Attribute */ +.highlight pre .nb { color: #268bd2 } /* Name.Builtin */ +.highlight pre .nc { color: #268bd2 } /* Name.Class */ +.highlight pre .no { color: #b58900 } /* Name.Constant */ +.highlight pre .nd { color: #cb4b16 } /* Name.Decorator */ +.highlight pre .ni { color: #cb4b16 } /* Name.Entity */ +.highlight pre .ne { color: #cb4b16 } /* Name.Exception */ +.highlight pre .nf { color: #268bd2 } /* Name.Function */ +.highlight pre .nl { color: #657b83 } /* Name.Label */ +.highlight pre .nn { color: #b58900 } /* Name.Namespace */ +.highlight pre .nx { color: #657b83 } /* Name.Other */ +.highlight pre .py { color: #268bd2 } /* Name.Property */ +.highlight pre .nt { color: #859900 } /* Name.Tag */ +.highlight pre .nv { color: #cb4b16 } /* Name.Variable */ +.highlight pre .ow { color: #859900 } /* Operator.Word */ +.highlight pre .w { color: #fdf6e3 } /* Text.Whitespace */ +.highlight pre .mf { color: #2aa198 } /* Literal.Number.Float */ +.highlight pre .mh { color: #2aa198 } /* Literal.Number.Hex */ +.highlight pre .mi { color: #2aa198 } /* Literal.Number.Integer */ +.highlight pre .mo { color: #2aa198 } /* Literal.Number.Oct */ +.highlight pre .sb { color: #2aa198 } /* Literal.String.Backtick */ +.highlight pre .sc { color: #2aa198 } /* Literal.String.Char */ +.highlight pre .sd { color: #2aa198 } /* Literal.String.Doc */ +.highlight pre .s2 { color: #2aa198 } /* Literal.String.Double */ +.highlight pre .se { color: #cb4b16 } /* Literal.String.Escape */ +.highlight pre .sh { color: #2aa198 } /* Literal.String.Heredoc */ +.highlight pre .si { color: #cb4b16 } /* Literal.String.Interpol */ +.highlight pre .sx { color: #2aa198 } /* Literal.String.Other */ +.highlight pre .sr { color: #2aa198 } /* Literal.String.Regex */ +.highlight pre .s1 { color: #2aa198 } /* Literal.String.Single */ +.highlight pre .ss { color: #2aa198 } /* Literal.String.Symbol */ +.highlight pre .bp { color: #268bd2; font-weight: bold } /* Name.Builtin.Pseudo */ +.highlight pre .vc { color: #268bd2 } /* Name.Variable.Class */ +.highlight pre .vg { color: #268bd2 } /* Name.Variable.Global */ +.highlight pre .vi { color: #268bd2 } /* Name.Variable.Instance */ +.highlight pre .il { color: #2aa198 } /* Literal.Number.Integer.Long */ diff --git a/theme/css/pygments/solarizedlight.css.gz b/theme/css/pygments/solarizedlight.css.gz new file mode 100644 index 000000000..4110033d9 Binary files /dev/null and b/theme/css/pygments/solarizedlight.css.gz differ diff --git a/theme/css/pygments/tango.css b/theme/css/pygments/tango.css new file mode 100644 index 000000000..a939077bd --- /dev/null +++ b/theme/css/pygments/tango.css @@ -0,0 +1,70 @@ +.highlight pre .hll { background-color: #ffffcc } +.highlight pre, .highlighttable pre { background: #f8f8f8; } +.highlight pre .c { color: #8f5902; font-style: italic } /* Comment */ +.highlight pre .err { color: #a40000; border: 1px solid #ef2929 } /* Error */ +.highlight pre .g { color: #000000 } /* Generic */ +.highlight pre .k { color: #204a87; font-weight: bold } /* Keyword */ +.highlight pre .l { color: #000000 } /* Literal */ +.highlight pre .n { color: #000000 } /* Name */ +.highlight pre .o { color: #ce5c00; font-weight: bold } /* Operator */ +.highlight pre .x { color: #000000 } /* Other */ +.highlight pre .p { color: #000000; font-weight: bold } /* Punctuation */ +.highlight pre .cm { color: #8f5902; font-style: italic } /* Comment.Multiline */ +.highlight pre .cp { color: #8f5902; font-style: italic } /* Comment.Preproc */ +.highlight pre .c1 { color: #8f5902; font-style: italic } /* Comment.Single */ +.highlight pre .cs { color: #8f5902; font-style: italic } /* Comment.Special */ +.highlight pre .gd { color: #a40000 } /* Generic.Deleted */ +.highlight pre .ge { color: #000000; font-style: italic } /* Generic.Emph */ +.highlight pre .gr { color: #ef2929 } /* Generic.Error */ +.highlight pre .gh { color: #000080; font-weight: bold } /* Generic.Heading */ +.highlight pre .gi { color: #00A000 } /* Generic.Inserted */ +.highlight pre .go { color: #000000; font-style: italic } /* Generic.Output */ +.highlight pre .gp { color: #8f5902 } /* Generic.Prompt */ +.highlight pre .gs { color: #000000; font-weight: bold } /* Generic.Strong */ +.highlight pre .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +.highlight pre .gt { color: #a40000; font-weight: bold } /* Generic.Traceback */ +.highlight pre .kc { color: #204a87; font-weight: bold } /* Keyword.Constant */ +.highlight pre .kd { color: #204a87; font-weight: bold } /* Keyword.Declaration */ +.highlight pre .kn { color: #204a87; font-weight: bold } /* Keyword.Namespace */ +.highlight pre .kp { color: #204a87; font-weight: bold } /* Keyword.Pseudo */ +.highlight pre .kr { color: #204a87; font-weight: bold } /* Keyword.Reserved */ +.highlight pre .kt { color: #204a87; font-weight: bold } /* Keyword.Type */ +.highlight pre .ld { color: #000000 } /* Literal.Date */ +.highlight pre .m { color: #0000cf; font-weight: bold } /* Literal.Number */ +.highlight pre .s { color: #4e9a06 } /* Literal.String */ +.highlight pre .na { color: #c4a000 } /* Name.Attribute */ +.highlight pre .nb { color: #204a87 } /* Name.Builtin */ +.highlight pre .nc { color: #000000 } /* Name.Class */ +.highlight pre .no { color: #000000 } /* Name.Constant */ +.highlight pre .nd { color: #5c35cc; font-weight: bold } /* Name.Decorator */ +.highlight pre .ni { color: #ce5c00 } /* Name.Entity */ +.highlight pre .ne { color: #cc0000; font-weight: bold } /* Name.Exception */ +.highlight pre .nf { color: #000000 } /* Name.Function */ +.highlight pre .nl { color: #f57900 } /* Name.Label */ +.highlight pre .nn { color: #000000 } /* Name.Namespace */ +.highlight pre .nx { color: #000000 } /* Name.Other */ +.highlight pre .py { color: #000000 } /* Name.Property */ +.highlight pre .nt { color: #204a87; font-weight: bold } /* Name.Tag */ +.highlight pre .nv { color: #000000 } /* Name.Variable */ +.highlight pre .ow { color: #204a87; font-weight: bold } /* Operator.Word */ +.highlight pre .w { color: #f8f8f8; text-decoration: underline } /* Text.Whitespace */ +.highlight pre .mf { color: #0000cf; font-weight: bold } /* Literal.Number.Float */ +.highlight pre .mh { color: #0000cf; font-weight: bold } /* Literal.Number.Hex */ +.highlight pre .mi { color: #0000cf; font-weight: bold } /* Literal.Number.Integer */ +.highlight pre .mo { color: #0000cf; font-weight: bold } /* Literal.Number.Oct */ +.highlight pre .sb { color: #4e9a06 } /* Literal.String.Backtick */ +.highlight pre .sc { color: #4e9a06 } /* Literal.String.Char */ +.highlight pre .sd { color: #8f5902; font-style: italic } /* Literal.String.Doc */ +.highlight pre .s2 { color: #4e9a06 } /* Literal.String.Double */ +.highlight pre .se { color: #4e9a06 } /* Literal.String.Escape */ +.highlight pre .sh { color: #4e9a06 } /* Literal.String.Heredoc */ +.highlight pre .si { color: #4e9a06 } /* Literal.String.Interpol */ +.highlight pre .sx { color: #4e9a06 } /* Literal.String.Other */ +.highlight pre .sr { color: #4e9a06 } /* Literal.String.Regex */ +.highlight pre .s1 { color: #4e9a06 } /* Literal.String.Single */ +.highlight pre .ss { color: #4e9a06 } /* Literal.String.Symbol */ +.highlight pre .bp { color: #3465a4 } /* Name.Builtin.Pseudo */ +.highlight pre .vc { color: #000000 } /* Name.Variable.Class */ +.highlight pre .vg { color: #000000 } /* Name.Variable.Global */ +.highlight pre .vi { color: #000000 } /* Name.Variable.Instance */ +.highlight pre .il { color: #0000cf; font-weight: bold } /* Literal.Number.Integer.Long */ diff --git a/theme/css/pygments/tango.css.gz b/theme/css/pygments/tango.css.gz new file mode 100644 index 000000000..fffee9d19 Binary files /dev/null and b/theme/css/pygments/tango.css.gz differ diff --git a/theme/css/pygments/trac.css b/theme/css/pygments/trac.css new file mode 100644 index 000000000..7f8d24d5f --- /dev/null +++ b/theme/css/pygments/trac.css @@ -0,0 +1,60 @@ +.highlight pre .hll { background-color: #ffffcc } +.highlight pre, .highlighttable pre { background: #ffffff; } +.highlight pre .c { color: #999988; font-style: italic } /* Comment */ +.highlight pre .err { color: #a61717; background-color: #e3d2d2 } /* Error */ +.highlight pre .k { font-weight: bold } /* Keyword */ +.highlight pre .o { font-weight: bold } /* Operator */ +.highlight pre .cm { color: #999988; font-style: italic } /* Comment.Multiline */ +.highlight pre .cp { color: #999999; font-weight: bold } /* Comment.Preproc */ +.highlight pre .c1 { color: #999988; font-style: italic } /* Comment.Single */ +.highlight pre .cs { color: #999999; font-weight: bold; font-style: italic } /* Comment.Special */ +.highlight pre .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ +.highlight pre .ge { font-style: italic } /* Generic.Emph */ +.highlight pre .gr { color: #aa0000 } /* Generic.Error */ +.highlight pre .gh { color: #999999 } /* Generic.Heading */ +.highlight pre .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ +.highlight pre .go { color: #888888 } /* Generic.Output */ +.highlight pre .gp { color: #555555 } /* Generic.Prompt */ +.highlight pre .gs { font-weight: bold } /* Generic.Strong */ +.highlight pre .gu { color: #aaaaaa } /* Generic.Subheading */ +.highlight pre .gt { color: #aa0000 } /* Generic.Traceback */ +.highlight pre .kc { font-weight: bold } /* Keyword.Constant */ +.highlight pre .kd { font-weight: bold } /* Keyword.Declaration */ +.highlight pre .kn { font-weight: bold } /* Keyword.Namespace */ +.highlight pre .kp { font-weight: bold } /* Keyword.Pseudo */ +.highlight pre .kr { font-weight: bold } /* Keyword.Reserved */ +.highlight pre .kt { color: #445588; font-weight: bold } /* Keyword.Type */ +.highlight pre .m { color: #009999 } /* Literal.Number */ +.highlight pre .s { color: #bb8844 } /* Literal.String */ +.highlight pre .na { color: #008080 } /* Name.Attribute */ +.highlight pre .nb { color: #999999 } /* Name.Builtin */ +.highlight pre .nc { color: #445588; font-weight: bold } /* Name.Class */ +.highlight pre .no { color: #008080 } /* Name.Constant */ +.highlight pre .ni { color: #800080 } /* Name.Entity */ +.highlight pre .ne { color: #990000; font-weight: bold } /* Name.Exception */ +.highlight pre .nf { color: #990000; font-weight: bold } /* Name.Function */ +.highlight pre .nn { color: #555555 } /* Name.Namespace */ +.highlight pre .nt { color: #000080 } /* Name.Tag */ +.highlight pre .nv { color: #008080 } /* Name.Variable */ +.highlight pre .ow { font-weight: bold } /* Operator.Word */ +.highlight pre .w { color: #bbbbbb } /* Text.Whitespace */ +.highlight pre .mf { color: #009999 } /* Literal.Number.Float */ +.highlight pre .mh { color: #009999 } /* Literal.Number.Hex */ +.highlight pre .mi { color: #009999 } /* Literal.Number.Integer */ +.highlight pre .mo { color: #009999 } /* Literal.Number.Oct */ +.highlight pre .sb { color: #bb8844 } /* Literal.String.Backtick */ +.highlight pre .sc { color: #bb8844 } /* Literal.String.Char */ +.highlight pre .sd { color: #bb8844 } /* Literal.String.Doc */ +.highlight pre .s2 { color: #bb8844 } /* Literal.String.Double */ +.highlight pre .se { color: #bb8844 } /* Literal.String.Escape */ +.highlight pre .sh { color: #bb8844 } /* Literal.String.Heredoc */ +.highlight pre .si { color: #bb8844 } /* Literal.String.Interpol */ +.highlight pre .sx { color: #bb8844 } /* Literal.String.Other */ +.highlight pre .sr { color: #808000 } /* Literal.String.Regex */ +.highlight pre .s1 { color: #bb8844 } /* Literal.String.Single */ +.highlight pre .ss { color: #bb8844 } /* Literal.String.Symbol */ +.highlight pre .bp { color: #999999 } /* Name.Builtin.Pseudo */ +.highlight pre .vc { color: #008080 } /* Name.Variable.Class */ +.highlight pre .vg { color: #008080 } /* Name.Variable.Global */ +.highlight pre .vi { color: #008080 } /* Name.Variable.Instance */ +.highlight pre .il { color: #009999 } /* Literal.Number.Integer.Long */ diff --git a/theme/css/pygments/trac.css.gz b/theme/css/pygments/trac.css.gz new file mode 100644 index 000000000..255ebdd4a Binary files /dev/null and b/theme/css/pygments/trac.css.gz differ diff --git a/theme/css/pygments/vim.css b/theme/css/pygments/vim.css new file mode 100644 index 000000000..7c8c17e54 --- /dev/null +++ b/theme/css/pygments/vim.css @@ -0,0 +1,70 @@ +.highlight pre .hll { background-color: #222222 } +.highlight pre, .highlighttable pre { background: #000000; color: #cccccc } +.highlight pre .c { color: #000080 } /* Comment */ +.highlight pre .err { color: #cccccc; border: 1px solid #FF0000 } /* Error */ +.highlight pre .g { color: #cccccc } /* Generic */ +.highlight pre .k { color: #cdcd00 } /* Keyword */ +.highlight pre .l { color: #cccccc } /* Literal */ +.highlight pre .n { color: #cccccc } /* Name */ +.highlight pre .o { color: #3399cc } /* Operator */ +.highlight pre .x { color: #cccccc } /* Other */ +.highlight pre .p { color: #cccccc } /* Punctuation */ +.highlight pre .cm { color: #000080 } /* Comment.Multiline */ +.highlight pre .cp { color: #000080 } /* Comment.Preproc */ +.highlight pre .c1 { color: #000080 } /* Comment.Single */ +.highlight pre .cs { color: #cd0000; font-weight: bold } /* Comment.Special */ +.highlight pre .gd { color: #cd0000 } /* Generic.Deleted */ +.highlight pre .ge { color: #cccccc; font-style: italic } /* Generic.Emph */ +.highlight pre .gr { color: #FF0000 } /* Generic.Error */ +.highlight pre .gh { color: #000080; font-weight: bold } /* Generic.Heading */ +.highlight pre .gi { color: #00cd00 } /* Generic.Inserted */ +.highlight pre .go { color: #888888 } /* Generic.Output */ +.highlight pre .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ +.highlight pre .gs { color: #cccccc; font-weight: bold } /* Generic.Strong */ +.highlight pre .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +.highlight pre .gt { color: #0044DD } /* Generic.Traceback */ +.highlight pre .kc { color: #cdcd00 } /* Keyword.Constant */ +.highlight pre .kd { color: #00cd00 } /* Keyword.Declaration */ +.highlight pre .kn { color: #cd00cd } /* Keyword.Namespace */ +.highlight pre .kp { color: #cdcd00 } /* Keyword.Pseudo */ +.highlight pre .kr { color: #cdcd00 } /* Keyword.Reserved */ +.highlight pre .kt { color: #00cd00 } /* Keyword.Type */ +.highlight pre .ld { color: #cccccc } /* Literal.Date */ +.highlight pre .m { color: #cd00cd } /* Literal.Number */ +.highlight pre .s { color: #cd0000 } /* Literal.String */ +.highlight pre .na { color: #cccccc } /* Name.Attribute */ +.highlight pre .nb { color: #cd00cd } /* Name.Builtin */ +.highlight pre .nc { color: #00cdcd } /* Name.Class */ +.highlight pre .no { color: #cccccc } /* Name.Constant */ +.highlight pre .nd { color: #cccccc } /* Name.Decorator */ +.highlight pre .ni { color: #cccccc } /* Name.Entity */ +.highlight pre .ne { color: #666699; font-weight: bold } /* Name.Exception */ +.highlight pre .nf { color: #cccccc } /* Name.Function */ +.highlight pre .nl { color: #cccccc } /* Name.Label */ +.highlight pre .nn { color: #cccccc } /* Name.Namespace */ +.highlight pre .nx { color: #cccccc } /* Name.Other */ +.highlight pre .py { color: #cccccc } /* Name.Property */ +.highlight pre .nt { color: #cccccc } /* Name.Tag */ +.highlight pre .nv { color: #00cdcd } /* Name.Variable */ +.highlight pre .ow { color: #cdcd00 } /* Operator.Word */ +.highlight pre .w { color: #cccccc } /* Text.Whitespace */ +.highlight pre .mf { color: #cd00cd } /* Literal.Number.Float */ +.highlight pre .mh { color: #cd00cd } /* Literal.Number.Hex */ +.highlight pre .mi { color: #cd00cd } /* Literal.Number.Integer */ +.highlight pre .mo { color: #cd00cd } /* Literal.Number.Oct */ +.highlight pre .sb { color: #cd0000 } /* Literal.String.Backtick */ +.highlight pre .sc { color: #cd0000 } /* Literal.String.Char */ +.highlight pre .sd { color: #cd0000 } /* Literal.String.Doc */ +.highlight pre .s2 { color: #cd0000 } /* Literal.String.Double */ +.highlight pre .se { color: #cd0000 } /* Literal.String.Escape */ +.highlight pre .sh { color: #cd0000 } /* Literal.String.Heredoc */ +.highlight pre .si { color: #cd0000 } /* Literal.String.Interpol */ +.highlight pre .sx { color: #cd0000 } /* Literal.String.Other */ +.highlight pre .sr { color: #cd0000 } /* Literal.String.Regex */ +.highlight pre .s1 { color: #cd0000 } /* Literal.String.Single */ +.highlight pre .ss { color: #cd0000 } /* Literal.String.Symbol */ +.highlight pre .bp { color: #cd00cd } /* Name.Builtin.Pseudo */ +.highlight pre .vc { color: #00cdcd } /* Name.Variable.Class */ +.highlight pre .vg { color: #00cdcd } /* Name.Variable.Global */ +.highlight pre .vi { color: #00cdcd } /* Name.Variable.Instance */ +.highlight pre .il { color: #cd00cd } /* Literal.Number.Integer.Long */ diff --git a/theme/css/pygments/vim.css.gz b/theme/css/pygments/vim.css.gz new file mode 100644 index 000000000..0a725e5a3 Binary files /dev/null and b/theme/css/pygments/vim.css.gz differ diff --git a/theme/css/pygments/vs.css b/theme/css/pygments/vs.css new file mode 100644 index 000000000..7a34130d5 --- /dev/null +++ b/theme/css/pygments/vs.css @@ -0,0 +1,34 @@ +.highlight pre .hll { background-color: #ffffcc } +.highlight pre, .highlighttable pre { background: #ffffff; } +.highlight pre .c { color: #008000 } /* Comment */ +.highlight pre .err { border: 1px solid #FF0000 } /* Error */ +.highlight pre .k { color: #0000ff } /* Keyword */ +.highlight pre .cm { color: #008000 } /* Comment.Multiline */ +.highlight pre .cp { color: #0000ff } /* Comment.Preproc */ +.highlight pre .c1 { color: #008000 } /* Comment.Single */ +.highlight pre .cs { color: #008000 } /* Comment.Special */ +.highlight pre .ge { font-style: italic } /* Generic.Emph */ +.highlight pre .gh { font-weight: bold } /* Generic.Heading */ +.highlight pre .gp { font-weight: bold } /* Generic.Prompt */ +.highlight pre .gs { font-weight: bold } /* Generic.Strong */ +.highlight pre .gu { font-weight: bold } /* Generic.Subheading */ +.highlight pre .kc { color: #0000ff } /* Keyword.Constant */ +.highlight pre .kd { color: #0000ff } /* Keyword.Declaration */ +.highlight pre .kn { color: #0000ff } /* Keyword.Namespace */ +.highlight pre .kp { color: #0000ff } /* Keyword.Pseudo */ +.highlight pre .kr { color: #0000ff } /* Keyword.Reserved */ +.highlight pre .kt { color: #2b91af } /* Keyword.Type */ +.highlight pre .s { color: #a31515 } /* Literal.String */ +.highlight pre .nc { color: #2b91af } /* Name.Class */ +.highlight pre .ow { color: #0000ff } /* Operator.Word */ +.highlight pre .sb { color: #a31515 } /* Literal.String.Backtick */ +.highlight pre .sc { color: #a31515 } /* Literal.String.Char */ +.highlight pre .sd { color: #a31515 } /* Literal.String.Doc */ +.highlight pre .s2 { color: #a31515 } /* Literal.String.Double */ +.highlight pre .se { color: #a31515 } /* Literal.String.Escape */ +.highlight pre .sh { color: #a31515 } /* Literal.String.Heredoc */ +.highlight pre .si { color: #a31515 } /* Literal.String.Interpol */ +.highlight pre .sx { color: #a31515 } /* Literal.String.Other */ +.highlight pre .sr { color: #a31515 } /* Literal.String.Regex */ +.highlight pre .s1 { color: #a31515 } /* Literal.String.Single */ +.highlight pre .ss { color: #a31515 } /* Literal.String.Symbol */ diff --git a/theme/css/pygments/vs.css.gz b/theme/css/pygments/vs.css.gz new file mode 100644 index 000000000..21e0c233a Binary files /dev/null and b/theme/css/pygments/vs.css.gz differ diff --git a/theme/css/pygments/zenburn.css b/theme/css/pygments/zenburn.css new file mode 100644 index 000000000..f295cf2cd --- /dev/null +++ b/theme/css/pygments/zenburn.css @@ -0,0 +1,70 @@ +.highlight pre .hll { background-color: #2f2f2f } +.highlight pre, .highlighttable pre { background: #3f3f3f; color: #dcdccc } +.highlight pre .c { color: #7f9f7f } /* Comment */ +.highlight pre .err { color: #e37170; background-color: #3d3535 } /* Error */ +.highlight pre .g { color: #dcdccc } /* Generic */ +.highlight pre .k { color: #f0dfaf; font-weight: bold } /* Keyword */ +.highlight pre .l { color: #dcdccc } /* Literal */ +.highlight pre .n { color: #dcdccc } /* Name */ +.highlight pre .o { color: #dcdccc } /* Operator */ +.highlight pre .x { color: #dcdccc } /* Other */ +.highlight pre .p { color: #dcdccc } /* Punctuation */ +.highlight pre .cm { color: #6CA0A3 } /* Comment.Multiline */ +.highlight pre .cp { color: #94bff3 } /* Comment.Preproc */ +.highlight pre .c1 { color: #7f9f7f } /* Comment.Single */ +.highlight pre .cs { color: #7f9f7f } /* Comment.Special */ +.highlight pre .gd { color: #dcdccc } /* Generic.Deleted */ +.highlight pre .ge { color: #dcdccc } /* Generic.Emph */ +.highlight pre .gr { color: #dcdccc } /* Generic.Error */ +.highlight pre .gh { color: #dcdccc } /* Generic.Heading */ +.highlight pre .gi { color: #dcdccc } /* Generic.Inserted */ +.highlight pre .go { color: #dcdccc } /* Generic.Output */ +.highlight pre .gp { color: #dcdccc } /* Generic.Prompt */ +.highlight pre .gs { color: #dcdccc } /* Generic.Strong */ +.highlight pre .gu { color: #dcdccc } /* Generic.Subheading */ +.highlight pre .gt { color: #dcdccc } /* Generic.Traceback */ +.highlight pre .kc { color: #bfebbf } /* Keyword.Constant */ +.highlight pre .kd { color: #f0dfaf; font-weight: bold } /* Keyword.Declaration */ +.highlight pre .kn { color: #f0dfaf; font-weight: bold } /* Keyword.Namespace */ +.highlight pre .kp { color: #dcdccc; font-weight: bold } /* Keyword.Pseudo */ +.highlight pre .kr { color: #dcdccc; font-weight: bold } /* Keyword.Reserved */ +.highlight pre .kt { color: #7cb8bb } /* Keyword.Type */ +.highlight pre .ld { color: #dcdccc } /* Literal.Date */ +.highlight pre .m { color: #8cd0d3 } /* Literal.Number */ +.highlight pre .s { color: #cc9393 } /* Literal.String */ +.highlight pre .na { color: #dcdccc } /* Name.Attribute */ +.highlight pre .nb { color: #93e0e3 } /* Name.Builtin */ +.highlight pre .nc { color: #7cb8bb } /* Name.Class */ +.highlight pre .no { color: #dcdccc } /* Name.Constant */ +.highlight pre .nd { color: #efef8f } /* Name.Decorator */ +.highlight pre .ni { color: #dcdccc } /* Name.Entity */ +.highlight pre .ne { color: #ebed9f; font-weight: bold } /* Name.Exception */ +.highlight pre .nf { color: #8cd0d3 } /* Name.Function */ +.highlight pre .nl { color: #f0dfaf } /* Name.Label */ +.highlight pre .nn { color: #dcdccc } /* Name.Namespace */ +.highlight pre .nx { color: #dcdccc } /* Name.Other */ +.highlight pre .py { color: #dcdccc } /* Name.Property */ +.highlight pre .nt { color: #dcdccc } /* Name.Tag */ +.highlight pre .nv { color: #dfaf8f } /* Name.Variable */ +.highlight pre .ow { color: #f0dfaf; font-weight: bold } /* Operator.Word */ +.highlight pre .w { color: #dcdccc } /* Text.Whitespace */ +.highlight pre .mf { color: #dcdccc } /* Literal.Number.Float */ +.highlight pre .mh { color: #dcdccc } /* Literal.Number.Hex */ +.highlight pre .mi { color: #dcdccc } /* Literal.Number.Integer */ +.highlight pre .mo { color: #dcdccc } /* Literal.Number.Oct */ +.highlight pre .sb { color: #cc9393 } /* Literal.String.Backtick */ +.highlight pre .sc { color: #cc9393 } /* Literal.String.Char */ +.highlight pre .sd { color: #cc9393 } /* Literal.String.Doc */ +.highlight pre .s2 { color: #cc9393 } /* Literal.String.Double */ +.highlight pre .se { color: #cc9393 } /* Literal.String.Escape */ +.highlight pre .sh { color: #cc9393 } /* Literal.String.Heredoc */ +.highlight pre .si { color: #cc9393 } /* Literal.String.Interpol */ +.highlight pre .sx { color: #cc9393 } /* Literal.String.Other */ +.highlight pre .sr { color: #cc9393 } /* Literal.String.Regex */ +.highlight pre .s1 { color: #cc9393 } /* Literal.String.Single */ +.highlight pre .ss { color: #cc9393 } /* Literal.String.Symbol */ +.highlight pre .bp { color: #f0dfaf; font-weight: bold } /* Name.Builtin.Pseudo */ +.highlight pre .vc { color: #efef8f } /* Name.Variable.Class */ +.highlight pre .vg { color: #dcdccc } /* Name.Variable.Global */ +.highlight pre .vi { color: #dcdccc } /* Name.Variable.Instance */ +.highlight pre .il { color: #8cd0d3 } /* Literal.Number.Integer.Long */ diff --git a/theme/css/pygments/zenburn.css.gz b/theme/css/pygments/zenburn.css.gz new file mode 100644 index 000000000..a577412e6 Binary files /dev/null and b/theme/css/pygments/zenburn.css.gz differ diff --git a/theme/css/w3.css b/theme/css/w3.css new file mode 100644 index 000000000..c95485a4f --- /dev/null +++ b/theme/css/w3.css @@ -0,0 +1,231 @@ +/* W3.CSS 4.10 February 2018 by Jan Egil and Borge Refsnes */ +html{box-sizing:border-box}*,*:before,*:after{box-sizing:inherit} +/* Extract from normalize.css by Nicolas Gallagher and Jonathan Neal git.io/normalize */ +html{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0} +article,aside,details,figcaption,figure,footer,header,main,menu,nav,section,summary{display:block} +audio,canvas,progress,video{display:inline-block}progress{vertical-align:baseline} +audio:not([controls]){display:none;height:0}[hidden],template{display:none} +a{background-color:transparent;-webkit-text-decoration-skip:objects} +a:active,a:hover{outline-width:0}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted} +dfn{font-style:italic}mark{background:#ff0;color:#000} +small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline} +sub{bottom:-0.25em}sup{top:-0.5em}figure{margin:1em 40px}img{border-style:none}svg:not(:root){overflow:hidden} +code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}hr{box-sizing:content-box;height:0;overflow:visible} +button,input,select,textarea{font:inherit;margin:0}optgroup{font-weight:bold} +button,input{overflow:visible}button,select{text-transform:none} +button,html [type=button],[type=reset],[type=submit]{-webkit-appearance:button} +button::-moz-focus-inner, [type=button]::-moz-focus-inner, [type=reset]::-moz-focus-inner, [type=submit]::-moz-focus-inner{border-style:none;padding:0} +button:-moz-focusring, [type=button]:-moz-focusring, [type=reset]:-moz-focusring, [type=submit]:-moz-focusring{outline:1px dotted ButtonText} +fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:.35em .625em .75em} +legend{color:inherit;display:table;max-width:100%;padding:0;white-space:normal}textarea{overflow:auto} +[type=checkbox],[type=radio]{padding:0} +[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto} +[type=search]{-webkit-appearance:textfield;outline-offset:-2px} +[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none} +::-webkit-input-placeholder{color:inherit;opacity:0.54} +::-webkit-file-upload-button{-webkit-appearance:button;font:inherit} +/* End extract */ +html,body{font-family:Verdana,sans-serif;font-size:15px;line-height:1.5}html{overflow-x:hidden} +h1{font-size:36px}h2{font-size:30px}h3{font-size:24px}h4{font-size:20px}h5{font-size:18px}h6{font-size:16px}.w3-serif{font-family:serif} +h1,h2,h3,h4,h5,h6{font-family:"Segoe UI",Arial,sans-serif;font-weight:400;margin:10px 0}.w3-wide{letter-spacing:4px} +hr{border:0;border-top:1px solid #eee;margin:20px 0} +.w3-image{max-width:100%;height:auto}img{vertical-align:middle}a{color:inherit} +.w3-table,.w3-table-all{border-collapse:collapse;border-spacing:0;width:100%;display:table}.w3-table-all{border:1px solid #ccc} +.w3-bordered tr,.w3-table-all tr{border-bottom:1px solid #ddd}.w3-striped tbody tr:nth-child(even){background-color:#f1f1f1} +.w3-table-all tr:nth-child(odd){background-color:#fff}.w3-table-all tr:nth-child(even){background-color:#f1f1f1} +.w3-hoverable tbody tr:hover,.w3-ul.w3-hoverable li:hover{background-color:#ccc}.w3-centered tr th,.w3-centered tr td{text-align:center} +.w3-table td,.w3-table th,.w3-table-all td,.w3-table-all th{padding:8px 8px;display:table-cell;text-align:left;vertical-align:top} +.w3-table th:first-child,.w3-table td:first-child,.w3-table-all th:first-child,.w3-table-all td:first-child{padding-left:16px} +.w3-btn,.w3-button{border:none;display:inline-block;padding:8px 16px;vertical-align:middle;overflow:hidden;text-decoration:none;color:inherit;background-color:inherit;text-align:center;cursor:pointer;white-space:nowrap} +.w3-btn:hover{box-shadow:0 8px 16px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19)} +.w3-btn,.w3-button{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none} +.w3-disabled,.w3-btn:disabled,.w3-button:disabled{cursor:not-allowed;opacity:0.3}.w3-disabled *,:disabled *{pointer-events:none} +.w3-btn.w3-disabled:hover,.w3-btn:disabled:hover{box-shadow:none} +.w3-badge,.w3-tag{background-color:#000;color:#fff;display:inline-block;padding-left:8px;padding-right:8px;text-align:center}.w3-badge{border-radius:50%} +.w3-ul{list-style-type:none;padding:0;margin:0}.w3-ul li{padding:8px 16px;border-bottom:1px solid #ddd}.w3-ul li:last-child{border-bottom:none} +.w3-tooltip,.w3-display-container{position:relative}.w3-tooltip .w3-text{display:none}.w3-tooltip:hover .w3-text{display:inline-block} +.w3-ripple:active{opacity:0.5}.w3-ripple{transition:opacity 0s} +.w3-input{padding:8px;display:block;border:none;border-bottom:1px solid #ccc;width:100%} +.w3-select{padding:9px 0;width:100%;border:none;border-bottom:1px solid #ccc} +.w3-dropdown-click,.w3-dropdown-hover{position:relative;display:inline-block;cursor:pointer} +.w3-dropdown-hover:hover .w3-dropdown-content{display:block} +.w3-dropdown-hover:first-child,.w3-dropdown-click:hover{background-color:#ccc;color:#000} +.w3-dropdown-hover:hover > .w3-button:first-child,.w3-dropdown-click:hover > .w3-button:first-child{background-color:#ccc;color:#000} +.w3-dropdown-content{cursor:auto;color:#000;background-color:#fff;display:none;position:absolute;min-width:160px;margin:0;padding:0;z-index:1} +.w3-check,.w3-radio{width:24px;height:24px;position:relative;top:6px} +.w3-sidebar{height:100%;width:200px;background-color:#fff;position:fixed!important;z-index:1;overflow:auto} +.w3-bar-block .w3-dropdown-hover,.w3-bar-block .w3-dropdown-click{width:100%} +.w3-bar-block .w3-dropdown-hover .w3-dropdown-content,.w3-bar-block .w3-dropdown-click .w3-dropdown-content{min-width:100%} +.w3-bar-block .w3-dropdown-hover .w3-button,.w3-bar-block .w3-dropdown-click .w3-button{width:100%;text-align:left;padding:8px 16px} +.w3-main,#main{transition:margin-left .4s} +.w3-modal{z-index:3;display:none;padding-top:100px;position:fixed;left:0;top:0;width:100%;height:100%;overflow:auto;background-color:rgb(0,0,0);background-color:rgba(0,0,0,0.4)} +.w3-modal-content{margin:auto;background-color:#fff;position:relative;padding:0;outline:0;width:600px} +.w3-bar{width:100%;overflow:hidden}.w3-center .w3-bar{display:inline-block;width:auto} +.w3-bar .w3-bar-item{padding:8px 16px;float:left;width:auto;border:none;display:block;outline:0} +.w3-bar .w3-dropdown-hover,.w3-bar .w3-dropdown-click{position:static;float:left} +.w3-bar .w3-button{white-space:normal} +.w3-bar-block .w3-bar-item{width:100%;display:block;padding:8px 16px;text-align:left;border:none;white-space:normal;float:none;outline:0} +.w3-bar-block.w3-center .w3-bar-item{text-align:center}.w3-block{display:block;width:100%} +.w3-responsive{display:block;overflow-x:auto} +.w3-container:after,.w3-container:before,.w3-panel:after,.w3-panel:before,.w3-row:after,.w3-row:before,.w3-row-padding:after,.w3-row-padding:before, +.w3-cell-row:before,.w3-cell-row:after,.w3-clear:after,.w3-clear:before,.w3-bar:before,.w3-bar:after{content:"";display:table;clear:both} +.w3-col,.w3-half,.w3-third,.w3-twothird,.w3-threequarter,.w3-quarter{float:left;width:100%} +.w3-col.s1{width:8.33333%}.w3-col.s2{width:16.66666%}.w3-col.s3{width:24.99999%}.w3-col.s4{width:33.33333%} +.w3-col.s5{width:41.66666%}.w3-col.s6{width:49.99999%}.w3-col.s7{width:58.33333%}.w3-col.s8{width:66.66666%} +.w3-col.s9{width:74.99999%}.w3-col.s10{width:83.33333%}.w3-col.s11{width:91.66666%}.w3-col.s12{width:99.99999%} +@media (min-width:601px){.w3-col.m1{width:8.33333%}.w3-col.m2{width:16.66666%}.w3-col.m3,.w3-quarter{width:24.99999%}.w3-col.m4,.w3-third{width:33.33333%} +.w3-col.m5{width:41.66666%}.w3-col.m6,.w3-half{width:49.99999%}.w3-col.m7{width:58.33333%}.w3-col.m8,.w3-twothird{width:66.66666%} +.w3-col.m9,.w3-threequarter{width:74.99999%}.w3-col.m10{width:83.33333%}.w3-col.m11{width:91.66666%}.w3-col.m12{width:99.99999%}} +@media (min-width:993px){.w3-col.l1{width:8.33333%}.w3-col.l2{width:16.66666%}.w3-col.l3{width:24.99999%}.w3-col.l4{width:33.33333%} +.w3-col.l5{width:41.66666%}.w3-col.l6{width:49.99999%}.w3-col.l7{width:58.33333%}.w3-col.l8{width:66.66666%} +.w3-col.l9{width:74.99999%}.w3-col.l10{width:83.33333%}.w3-col.l11{width:91.66666%}.w3-col.l12{width:99.99999%}} +.w3-content{max-width:980px;margin:auto}.w3-rest{overflow:hidden} +.w3-cell-row{display:table;width:100%}.w3-cell{display:table-cell} +.w3-cell-top{vertical-align:top}.w3-cell-middle{vertical-align:middle}.w3-cell-bottom{vertical-align:bottom} +.w3-hide{display:none!important}.w3-show-block,.w3-show{display:block!important}.w3-show-inline-block{display:inline-block!important} +@media (max-width:600px){.w3-modal-content{margin:0 10px;width:auto!important}.w3-modal{padding-top:30px} +.w3-dropdown-hover.w3-mobile .w3-dropdown-content,.w3-dropdown-click.w3-mobile .w3-dropdown-content{position:relative} +.w3-hide-small{display:none!important}.w3-mobile{display:block;width:100%!important}.w3-bar-item.w3-mobile,.w3-dropdown-hover.w3-mobile,.w3-dropdown-click.w3-mobile{text-align:center} +.w3-dropdown-hover.w3-mobile,.w3-dropdown-hover.w3-mobile .w3-btn,.w3-dropdown-hover.w3-mobile .w3-button,.w3-dropdown-click.w3-mobile,.w3-dropdown-click.w3-mobile .w3-btn,.w3-dropdown-click.w3-mobile .w3-button{width:100%}} +@media (max-width:768px){.w3-modal-content{width:500px}.w3-modal{padding-top:50px}} +@media (min-width:993px){.w3-modal-content{width:900px}.w3-hide-large{display:none!important}.w3-sidebar.w3-collapse{display:block!important}} +@media (max-width:992px) and (min-width:601px){.w3-hide-medium{display:none!important}} +@media (max-width:992px){.w3-sidebar.w3-collapse{display:none}.w3-main{margin-left:0!important;margin-right:0!important}} +.w3-top,.w3-bottom{position:fixed;width:100%;z-index:1}.w3-top{top:0}.w3-bottom{bottom:0} +.w3-overlay{position:fixed;display:none;width:100%;height:100%;top:0;left:0;right:0;bottom:0;background-color:rgba(0,0,0,0.5);z-index:2} +.w3-display-topleft{position:absolute;left:0;top:0}.w3-display-topright{position:absolute;right:0;top:0} +.w3-display-bottomleft{position:absolute;left:0;bottom:0}.w3-display-bottomright{position:absolute;right:0;bottom:0} +.w3-display-middle{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%)} +.w3-display-left{position:absolute;top:50%;left:0%;transform:translate(0%,-50%);-ms-transform:translate(-0%,-50%)} +.w3-display-right{position:absolute;top:50%;right:0%;transform:translate(0%,-50%);-ms-transform:translate(0%,-50%)} +.w3-display-topmiddle{position:absolute;left:50%;top:0;transform:translate(-50%,0%);-ms-transform:translate(-50%,0%)} +.w3-display-bottommiddle{position:absolute;left:50%;bottom:0;transform:translate(-50%,0%);-ms-transform:translate(-50%,0%)} +.w3-display-container:hover .w3-display-hover{display:block}.w3-display-container:hover span.w3-display-hover{display:inline-block}.w3-display-hover{display:none} +.w3-display-position{position:absolute} +.w3-circle{border-radius:50%} +.w3-round-small{border-radius:2px}.w3-round,.w3-round-medium{border-radius:4px}.w3-round-large{border-radius:8px}.w3-round-xlarge{border-radius:16px}.w3-round-xxlarge{border-radius:32px} +.w3-row-padding,.w3-row-padding>.w3-half,.w3-row-padding>.w3-third,.w3-row-padding>.w3-twothird,.w3-row-padding>.w3-threequarter,.w3-row-padding>.w3-quarter,.w3-row-padding>.w3-col{padding:0 8px} +.w3-container,.w3-panel{padding:0.01em 16px}.w3-panel{margin-top:16px;margin-bottom:16px} +.w3-code,.w3-codespan{font-family:Consolas,"courier new";font-size:16px} +.w3-code{width:auto;background-color:#fff;padding:8px 12px;border-left:4px solid #4CAF50;word-wrap:break-word} +.w3-codespan{color:crimson;background-color:#f1f1f1;padding-left:4px;padding-right:4px;font-size:110%} +.w3-card,.w3-card-2{box-shadow:0 2px 5px 0 rgba(0,0,0,0.16),0 2px 10px 0 rgba(0,0,0,0.12)} +.w3-card-4,.w3-hover-shadow:hover{box-shadow:0 4px 10px 0 rgba(0,0,0,0.2),0 4px 20px 0 rgba(0,0,0,0.19)} +.w3-spin{animation:w3-spin 2s infinite linear}@keyframes w3-spin{0%{transform:rotate(0deg)}100%{transform:rotate(359deg)}} +.w3-animate-fading{animation:fading 10s infinite}@keyframes fading{0%{opacity:0}50%{opacity:1}100%{opacity:0}} +.w3-animate-opacity{animation:opac 0.8s}@keyframes opac{from{opacity:0} to{opacity:1}} +.w3-animate-top{position:relative;animation:animatetop 0.4s}@keyframes animatetop{from{top:-300px;opacity:0} to{top:0;opacity:1}} +.w3-animate-left{position:relative;animation:animateleft 0.4s}@keyframes animateleft{from{left:-300px;opacity:0} to{left:0;opacity:1}} +.w3-animate-right{position:relative;animation:animateright 0.4s}@keyframes animateright{from{right:-300px;opacity:0} to{right:0;opacity:1}} +.w3-animate-bottom{position:relative;animation:animatebottom 0.4s}@keyframes animatebottom{from{bottom:-300px;opacity:0} to{bottom:0;opacity:1}} +.w3-animate-zoom {animation:animatezoom 0.6s}@keyframes animatezoom{from{transform:scale(0)} to{transform:scale(1)}} +.w3-animate-input{transition:width 0.4s ease-in-out}.w3-animate-input:focus{width:100%!important} +.w3-opacity,.w3-hover-opacity:hover{opacity:0.60}.w3-opacity-off,.w3-hover-opacity-off:hover{opacity:1} +.w3-opacity-max{opacity:0.25}.w3-opacity-min{opacity:0.75} +.w3-greyscale-max,.w3-grayscale-max,.w3-hover-greyscale:hover,.w3-hover-grayscale:hover{filter:grayscale(100%)} +.w3-greyscale,.w3-grayscale{filter:grayscale(75%)}.w3-greyscale-min,.w3-grayscale-min{filter:grayscale(50%)} +.w3-sepia{filter:sepia(75%)}.w3-sepia-max,.w3-hover-sepia:hover{filter:sepia(100%)}.w3-sepia-min{filter:sepia(50%)} +.w3-tiny{font-size:10px!important}.w3-small{font-size:12px!important}.w3-medium{font-size:15px!important}.w3-large{font-size:18px!important} +.w3-xlarge{font-size:24px!important}.w3-xxlarge{font-size:36px!important}.w3-xxxlarge{font-size:48px!important}.w3-jumbo{font-size:64px!important} +.w3-left-align{text-align:left!important}.w3-right-align{text-align:right!important}.w3-justify{text-align:justify!important}.w3-center{text-align:center!important} +.w3-border-0{border:0!important}.w3-border{border:1px solid #ccc!important} +.w3-border-top{border-top:1px solid #ccc!important}.w3-border-bottom{border-bottom:1px solid #ccc!important} +.w3-border-left{border-left:1px solid #ccc!important}.w3-border-right{border-right:1px solid #ccc!important} +.w3-topbar{border-top:6px solid #ccc!important}.w3-bottombar{border-bottom:6px solid #ccc!important} +.w3-leftbar{border-left:6px solid #ccc!important}.w3-rightbar{border-right:6px solid #ccc!important} +.w3-section,.w3-code{margin-top:16px!important;margin-bottom:16px!important} +.w3-margin{margin:16px!important}.w3-margin-top{margin-top:16px!important}.w3-margin-bottom{margin-bottom:16px!important} +.w3-margin-left{margin-left:16px!important}.w3-margin-right{margin-right:16px!important} +.w3-padding-small{padding:4px 8px!important}.w3-padding{padding:8px 16px!important}.w3-padding-large{padding:12px 24px!important} +.w3-padding-16{padding-top:16px!important;padding-bottom:16px!important}.w3-padding-24{padding-top:24px!important;padding-bottom:24px!important} +.w3-padding-32{padding-top:32px!important;padding-bottom:32px!important}.w3-padding-48{padding-top:48px!important;padding-bottom:48px!important} +.w3-padding-64{padding-top:64px!important;padding-bottom:64px!important} +.w3-left{float:left!important}.w3-right{float:right!important} +.w3-button:hover{color:#000!important;background-color:#ccc!important} +.w3-transparent,.w3-hover-none:hover{background-color:transparent!important} +.w3-hover-none:hover{box-shadow:none!important} +/* Colors */ +.w3-amber,.w3-hover-amber:hover{color:#000!important;background-color:#ffc107!important} +.w3-aqua,.w3-hover-aqua:hover{color:#000!important;background-color:#00ffff!important} +.w3-blue,.w3-hover-blue:hover{color:#fff!important;background-color:#2196F3!important} +.w3-light-blue,.w3-hover-light-blue:hover{color:#000!important;background-color:#87CEEB!important} +.w3-brown,.w3-hover-brown:hover{color:#fff!important;background-color:#795548!important} +.w3-cyan,.w3-hover-cyan:hover{color:#000!important;background-color:#00bcd4!important} +.w3-blue-grey,.w3-hover-blue-grey:hover,.w3-blue-gray,.w3-hover-blue-gray:hover{color:#fff!important;background-color:#607d8b!important} +.w3-green,.w3-hover-green:hover{color:#fff!important;background-color:#4CAF50!important} +.w3-light-green,.w3-hover-light-green:hover{color:#000!important;background-color:#8bc34a!important} +.w3-indigo,.w3-hover-indigo:hover{color:#fff!important;background-color:#3f51b5!important} +.w3-khaki,.w3-hover-khaki:hover{color:#000!important;background-color:#f0e68c!important} +.w3-lime,.w3-hover-lime:hover{color:#000!important;background-color:#cddc39!important} +.w3-orange,.w3-hover-orange:hover{color:#000!important;background-color:#ff9800!important} +.w3-deep-orange,.w3-hover-deep-orange:hover{color:#fff!important;background-color:#ff5722!important} +.w3-pink,.w3-hover-pink:hover{color:#fff!important;background-color:#e91e63!important} +.w3-purple,.w3-hover-purple:hover{color:#fff!important;background-color:#9c27b0!important} +.w3-deep-purple,.w3-hover-deep-purple:hover{color:#fff!important;background-color:#673ab7!important} +.w3-red,.w3-hover-red:hover{color:#fff!important;background-color:#f44336!important} +.w3-sand,.w3-hover-sand:hover{color:#000!important;background-color:#fdf5e6!important} +.w3-teal,.w3-hover-teal:hover{color:#fff!important;background-color:#009688!important} +.w3-yellow,.w3-hover-yellow:hover{color:#000!important;background-color:#ffeb3b!important} +.w3-white,.w3-hover-white:hover{color:#000!important;background-color:#fff!important} +.w3-black,.w3-hover-black:hover{color:#fff!important;background-color:#000!important} +.w3-grey,.w3-hover-grey:hover,.w3-gray,.w3-hover-gray:hover{color:#000!important;background-color:#9e9e9e!important} +.w3-light-grey,.w3-hover-light-grey:hover,.w3-light-gray,.w3-hover-light-gray:hover{color:#000!important;background-color:#f1f1f1!important} +.w3-dark-grey,.w3-hover-dark-grey:hover,.w3-dark-gray,.w3-hover-dark-gray:hover{color:#fff!important;background-color:#616161!important} +.w3-pale-red,.w3-hover-pale-red:hover{color:#000!important;background-color:#ffdddd!important} +.w3-pale-green,.w3-hover-pale-green:hover{color:#000!important;background-color:#ddffdd!important} +.w3-pale-yellow,.w3-hover-pale-yellow:hover{color:#000!important;background-color:#ffffcc!important} +.w3-pale-blue,.w3-hover-pale-blue:hover{color:#000!important;background-color:#ddffff!important} +.w3-text-amber,.w3-hover-text-amber:hover{color:#ffc107!important} +.w3-text-aqua,.w3-hover-text-aqua:hover{color:#00ffff!important} +.w3-text-blue,.w3-hover-text-blue:hover{color:#2196F3!important} +.w3-text-light-blue,.w3-hover-text-light-blue:hover{color:#87CEEB!important} +.w3-text-brown,.w3-hover-text-brown:hover{color:#795548!important} +.w3-text-cyan,.w3-hover-text-cyan:hover{color:#00bcd4!important} +.w3-text-blue-grey,.w3-hover-text-blue-grey:hover,.w3-text-blue-gray,.w3-hover-text-blue-gray:hover{color:#607d8b!important} +.w3-text-green,.w3-hover-text-green:hover{color:#4CAF50!important} +.w3-text-light-green,.w3-hover-text-light-green:hover{color:#8bc34a!important} +.w3-text-indigo,.w3-hover-text-indigo:hover{color:#3f51b5!important} +.w3-text-khaki,.w3-hover-text-khaki:hover{color:#b4aa50!important} +.w3-text-lime,.w3-hover-text-lime:hover{color:#cddc39!important} +.w3-text-orange,.w3-hover-text-orange:hover{color:#ff9800!important} +.w3-text-deep-orange,.w3-hover-text-deep-orange:hover{color:#ff5722!important} +.w3-text-pink,.w3-hover-text-pink:hover{color:#e91e63!important} +.w3-text-purple,.w3-hover-text-purple:hover{color:#9c27b0!important} +.w3-text-deep-purple,.w3-hover-text-deep-purple:hover{color:#673ab7!important} +.w3-text-red,.w3-hover-text-red:hover{color:#f44336!important} +.w3-text-sand,.w3-hover-text-sand:hover{color:#fdf5e6!important} +.w3-text-teal,.w3-hover-text-teal:hover{color:#009688!important} +.w3-text-yellow,.w3-hover-text-yellow:hover{color:#d2be0e!important} +.w3-text-white,.w3-hover-text-white:hover{color:#fff!important} +.w3-text-black,.w3-hover-text-black:hover{color:#000!important} +.w3-text-grey,.w3-hover-text-grey:hover,.w3-text-gray,.w3-hover-text-gray:hover{color:#757575!important} +.w3-text-light-grey,.w3-hover-text-light-grey:hover,.w3-text-light-gray,.w3-hover-text-light-gray:hover{color:#f1f1f1!important} +.w3-text-dark-grey,.w3-hover-text-dark-grey:hover,.w3-text-dark-gray,.w3-hover-text-dark-gray:hover{color:#3a3a3a!important} +.w3-border-amber,.w3-hover-border-amber:hover{border-color:#ffc107!important} +.w3-border-aqua,.w3-hover-border-aqua:hover{border-color:#00ffff!important} +.w3-border-blue,.w3-hover-border-blue:hover{border-color:#2196F3!important} +.w3-border-light-blue,.w3-hover-border-light-blue:hover{border-color:#87CEEB!important} +.w3-border-brown,.w3-hover-border-brown:hover{border-color:#795548!important} +.w3-border-cyan,.w3-hover-border-cyan:hover{border-color:#00bcd4!important} +.w3-border-blue-grey,.w3-hover-border-blue-grey:hover,.w3-border-blue-gray,.w3-hover-border-blue-gray:hover{border-color:#607d8b!important} +.w3-border-green,.w3-hover-border-green:hover{border-color:#4CAF50!important} +.w3-border-light-green,.w3-hover-border-light-green:hover{border-color:#8bc34a!important} +.w3-border-indigo,.w3-hover-border-indigo:hover{border-color:#3f51b5!important} +.w3-border-khaki,.w3-hover-border-khaki:hover{border-color:#f0e68c!important} +.w3-border-lime,.w3-hover-border-lime:hover{border-color:#cddc39!important} +.w3-border-orange,.w3-hover-border-orange:hover{border-color:#ff9800!important} +.w3-border-deep-orange,.w3-hover-border-deep-orange:hover{border-color:#ff5722!important} +.w3-border-pink,.w3-hover-border-pink:hover{border-color:#e91e63!important} +.w3-border-purple,.w3-hover-border-purple:hover{border-color:#9c27b0!important} +.w3-border-deep-purple,.w3-hover-border-deep-purple:hover{border-color:#673ab7!important} +.w3-border-red,.w3-hover-border-red:hover{border-color:#f44336!important} +.w3-border-sand,.w3-hover-border-sand:hover{border-color:#fdf5e6!important} +.w3-border-teal,.w3-hover-border-teal:hover{border-color:#009688!important} +.w3-border-yellow,.w3-hover-border-yellow:hover{border-color:#ffeb3b!important} +.w3-border-white,.w3-hover-border-white:hover{border-color:#fff!important} +.w3-border-black,.w3-hover-border-black:hover{border-color:#000!important} +.w3-border-grey,.w3-hover-border-grey:hover,.w3-border-gray,.w3-hover-border-gray:hover{border-color:#9e9e9e!important} +.w3-border-light-grey,.w3-hover-border-light-grey:hover,.w3-border-light-gray,.w3-hover-border-light-gray:hover{border-color:#f1f1f1!important} +.w3-border-dark-grey,.w3-hover-border-dark-grey:hover,.w3-border-dark-gray,.w3-hover-border-dark-gray:hover{border-color:#616161!important} +.w3-border-pale-red,.w3-hover-border-pale-red:hover{border-color:#ffe7e7!important}.w3-border-pale-green,.w3-hover-border-pale-green:hover{border-color:#e7ffe7!important} +.w3-border-pale-yellow,.w3-hover-border-pale-yellow:hover{border-color:#ffffcc!important}.w3-border-pale-blue,.w3-hover-border-pale-blue:hover{border-color:#e7ffff!important} \ No newline at end of file diff --git a/theme/css/w3.css.gz b/theme/css/w3.css.gz new file mode 100644 index 000000000..04f4b217f Binary files /dev/null and b/theme/css/w3.css.gz differ diff --git a/top_level_statement_csharp_9.html b/top_level_statement_csharp_9.html new file mode 100644 index 000000000..273e2bbca --- /dev/null +++ b/top_level_statement_csharp_9.html @@ -0,0 +1,513 @@ + + + + + + + + Top Level Statement in C# 9 - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Top Level Statement in C# 9

+
+ +
+
+ +
+

Hey folks, I'm coming along to tell you a few things about the new feature of C# 9. Every time you want to start a new project, you always have the same Main File, with the same structure. At the next version of C# (version 9), we'll have a new feature called Top Level Statement. With that, we'll be able to code our app without any namespace/class/public void static main structure. Take a look at the code below.

+
using System;
+
+Console.WriteLine("Hello World!");
+
+ +

It looks pretty simple, but with this, you can play around with your code, and even code a simple/tiny Web API. To start playing with the new features, firstly download the .net 5 SDK and change your .csproj file to target the .net 5 and language preview like bellow.

+
<Project Sdk="Microsoft.NET.Sdk">
+  <PropertyGroup>
+    <OutputType>Exe</OutputType>
+    <TargetFramework>net5.0</TargetFramework>
+    <LangVersion>preview</LangVersion>
+  </PropertyGroup>
+</Project>
+
+ +

And you're ready to play with the awesome features available in the preview. Let's code a way to get the image of the day from NASA API and print the Picture of the Day. No awesome code here, it's really a way to show how simple a simple call could be. After here, why not save the image in a file? Maybe send the file over telegram?

+
using System;
+using System.Net.Http;
+using System.Text.Json;
+
+var API = "https://api.nasa.gov/planetary/apod?hd=true&api_key=DEMO_KEY";
+var cli = new HttpClient();
+
+var response = await cli.GetAsync(API);
+var data = JsonSerializer.Deserialize<NasaApi>(await response.Content.ReadAsStringAsync());
+
+Console.WriteLine(data.Url);
+
+ +

That's it for today folks. Keep an eye open for the awesome features C# 9 will bring to us, there's plenty more features already available.

+
+ + +
+
+

Translations:

+ +
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/top_level_statement_csharp_9.html.gz b/top_level_statement_csharp_9.html.gz new file mode 100644 index 000000000..b2537e84b Binary files /dev/null and b/top_level_statement_csharp_9.html.gz differ diff --git a/using_git_hooks_easy_your_life.html b/using_git_hooks_easy_your_life.html new file mode 100644 index 000000000..54bd46ca2 --- /dev/null +++ b/using_git_hooks_easy_your_life.html @@ -0,0 +1,515 @@ + + + + + + + + Using git hooks to easy your life - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Using git hooks to easy your life

+
+ +
+
+ +
+

Hey folks, it's been a time since my last post. In the meantime, I moved to another state, changed job, and started learning new kinds of stuff. Today I would like to share one thing that I usually do with my small git projects. Git has many cool features, git hooks were one of them. I'll talk about the pre-commit hook today.

+

Let's say that, for some reason, you don't have a CI tool/server running after every commit and you want to enforce that every developer runs the tests before every commit? Git pre-commit to the rescue. You can code the hooks with shell, ruby, python, and I could be wrong, but even PHP would work. pre-commit is a client-side hook (we have server side too) and he's located inside the .git/hooks folder. Let's jump to the code... Create a file called 'pre-commit' inside that folder with the following code.

+
#!/bin/bash
+npm test # assuming you're using it inside a nodeJS project
+
+

Don't forget to make the script executable!! Now break your test and try to commit. That's easy but can save you from breaking the tests at the main CI/Travis/Codeship/etc and being notified by email :). Why not even validate the lint of your project or check if the coverage doesn't fall? Does your team/company have a patter for commit messages? No problem, there is a hook called commit-msg that you can use to validate your message.

+

+
+ + +
+
+

Translations:

+
    +
+
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/using_git_hooks_easy_your_life.html.gz b/using_git_hooks_easy_your_life.html.gz new file mode 100644 index 000000000..76b3366de Binary files /dev/null and b/using_git_hooks_easy_your_life.html.gz differ diff --git a/zabbix-icmp-pinger-processes-more-than-75.html b/zabbix-icmp-pinger-processes-more-than-75.html new file mode 100644 index 000000000..f130faf19 --- /dev/null +++ b/zabbix-icmp-pinger-processes-more-than-75.html @@ -0,0 +1,524 @@ + + + + + + + + Zabbix ICMP pinger processes more than 75% - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Zabbix ICMP pinger processes more than 75%

+
+ +
+
+ +
+

So your monitoring sytems have grown and your zabbix started loggin "Zabbix icmp pinger processes more than 75% busy" at the dashboard.

+

Dashboard do zabbix avisando sobre o erro

+

All you have to do is open your config file (/etc/zabbix/zabbix_server.conf) and find the a tag named StartPingers. It'll be commented by default. Uncomment it and set it's value to something like 3 or 4. It should solve your problem.

+
### Option: StartPingers
+#       Number of pre-forked instances of ICMP pingers.
+#
+# Mandatory: no
+# Range: 0-1000
+# Default:
+StartPingers=4
+
+ +

How many Pingers do I need?

+

Well, there is no exact answer to this. If you set it too high, you'll be wasting resources. The best way to solve, it's increasing them as soon as you notice the percentage growing.

+
+ + +
+
+

Translations:

+ +
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/zabbix-icmp-pinger-processes-more-than-75.html.gz b/zabbix-icmp-pinger-processes-more-than-75.html.gz new file mode 100644 index 000000000..0ac3cd9bf Binary files /dev/null and b/zabbix-icmp-pinger-processes-more-than-75.html.gz differ diff --git a/zabbix-poller-processes-more-than-75.html b/zabbix-poller-processes-more-than-75.html new file mode 100644 index 000000000..2413a1877 --- /dev/null +++ b/zabbix-poller-processes-more-than-75.html @@ -0,0 +1,565 @@ + + + + + + + + Zabbix poller processes more than 75% - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Zabbix poller processes more than 75%

+
+ +
+
+ +
+

Hey folks, this is the third post about tweaking the Zabbix configurations. All changes that I've suggested here were based on a Zabbix Server with 50+ hosts. Another thing that can happen to your server, it's the poller get overwhelmed by the amount of servers that need to be polled plus the ones that are not responding. Bellow two images where you can see the log and the graphic where you can see the usage percent.

+

Dashboard log about the poller processes

+

Graph showing the utilization percent of each collector

+

To solve, let's go back to the zabbix_server.conf file and find two variables, StartPollers and StartPollersUnreachable. Increase them as needed. There's no magic number, you must see what works for you. But keep in mind that the StartPollersUnreachable is responsible for that host that can't be "reached" (of course) and will hold your poller more time.

+
### Option: StartPollers
+#       Number of pre-forked instances of pollers.
+#
+# Mandatory: no
+# Range: 0-1000
+# Default:
+StartPollers=20
+
+#...
+
+### Option: StartPollersUnreachable
+#       Number of pre-forked instances of pollers for unreachable hosts (including IPMI and Java).
+#       At least one poller for unreachable hosts must be running if regular, IPMI or Java pollers
+#       are started.
+#
+# Mandatory: no
+# Range: 0-1000
+# Default:
+StartPollersUnreachable=5
+
+ +

After the change, restart the server and wait a few moments and take a look again at your dashboard. Bellow the effect that I've got.

+

Graph showing the new utilization percent of the processes after the changes

+
+ + +
+
+

Translations:

+ +
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/zabbix-poller-processes-more-than-75.html.gz b/zabbix-poller-processes-more-than-75.html.gz new file mode 100644 index 000000000..65f6c794f Binary files /dev/null and b/zabbix-poller-processes-more-than-75.html.gz differ diff --git a/zabbix-running-on-low-memory-mode.html b/zabbix-running-on-low-memory-mode.html new file mode 100644 index 000000000..82c5a4d8d --- /dev/null +++ b/zabbix-running-on-low-memory-mode.html @@ -0,0 +1,554 @@ + + + + + + + + Zabbix Running on Low Memory Mode - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Zabbix Running on Low Memory Mode

+
+ +
+
+ +
+

Hey folks, another Zabbix post today. This one it's about increasing the Zabbix Server Cache. It's pretty common (if you have the default settings only) get a warning about your Zabbix value cache running on low memory mode at your dashboard or logs.

+

Zabbix Dashboard warning about the memory problem +Zabbix Dashboard cache graph 70% used

+

To solve, go back to your Zabbix config file (zabbix_server.conf) and look for the tag CacheSize. Uncomment it and set to a value bigger than 8M (8M it's the default value). In my case, we set a cache of 100M. After the change, restart the service.

+
### Option: CacheSize
+#       Size of configuration cache, in bytes.
+#       Shared memory size for storing host, item and trigger data.
+#
+# Mandatory: no
+# Range: 128K-64G
+# Default:
+CacheSize=100M #uncomment this line
+
+ +

Zabbix Dashboard resolved memory problem

+

See ya folks.

+
+ + +
+
+

Translations:

+ +
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/zabbix-running-on-low-memory-mode.html.gz b/zabbix-running-on-low-memory-mode.html.gz new file mode 100644 index 000000000..7e44f67e6 Binary files /dev/null and b/zabbix-running-on-low-memory-mode.html.gz differ diff --git a/zabbix-server-out-of-memory-crash.html b/zabbix-server-out-of-memory-crash.html new file mode 100644 index 000000000..0ed216e32 --- /dev/null +++ b/zabbix-server-out-of-memory-crash.html @@ -0,0 +1,546 @@ + + + + + + + + Zabbix Server Out of Memory - Sipmann + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
+ +
+
+
+

Zabbix Server Out of Memory

+
+ +
+
+ +
+

Do you have a crashing Zabbix Server and looking through the log /var/log/zabbix/zabbix_server.log you see the following out of memory message?

+
__mem_malloc: skipped 0 asked 24 skip_min 18446744073709551615 skip_max 0
+[file:dbconfig.c,line:94] __zbx_mem_realloc(): out of memory (requested 16 bytes)
+[file:dbconfig.c,line:94] __zbx_mem_realloc(): please increase CacheSize configuration parameter
+
+ +

Besides the clear solution to the error, that's a common issue on servers that have a few monitoring items on it (servers, switches, firewalls, databases, etc...). To solve, go to your zabbix_server.conf and look for the CacheSize property and set it to a higher value. Its default should be 8M. At a customer that has somewhere between 4 servers, 7 firewalls/appliances, and a few other things, a 32M did the job, but you can set up to 8G.

+

See ya folks.

+
+ + +
+
+

Translations:

+ +
+ +
+ +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/zabbix-server-out-of-memory-crash.html.gz b/zabbix-server-out-of-memory-crash.html.gz new file mode 100644 index 000000000..c9f2a11ba Binary files /dev/null and b/zabbix-server-out-of-memory-crash.html.gz differ