{"id":2841,"date":"2026-03-14T07:36:51","date_gmt":"2026-03-14T07:36:51","guid":{"rendered":"https:\/\/cloudzeninnovations.com\/dev\/?p=2841"},"modified":"2026-03-14T07:36:51","modified_gmt":"2026-03-14T07:36:51","slug":"linux-service-monitoring-on-azure-vms-with-custom-logs-dcrs","status":"publish","type":"post","link":"https:\/\/cloudzeninnovations.com\/dev\/linux-service-monitoring-on-azure-vms-with-custom-logs-dcrs\/","title":{"rendered":"Linux Service Monitoring on Azure VMs with Custom Logs &#038; DCRs"},"content":{"rendered":"<p>In hybrid and cloud-native environments, monitoring custom services and background jobs on VMs is critical for uptime and actions. In this article, we&#8217;ll walk through how to collect service status logs (e.g., running\/stopped) from Azure VMs and push them to a custom Log Analytics table using Data Collection Rules (DCRs).<\/p>\n<h4>Use Case Overview:<\/h4>\n<ul>\n<li>Monitor services like nginx, MySQL, or any custom service.<\/li>\n<li>Automate log collection using bash + cron.<\/li>\n<li>Centralize logs in Azure Monitor for querying, alerts, and dashboards.<\/li>\n<\/ul>\n<h5>Architecture Diagram<\/h5>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-2843\" src=\"https:\/\/cloudzeninnovations.com\/dev\/wp-content\/uploads\/2026\/03\/Linux-Service-Monitoring-Architecture-Diagram.jpg\" alt=\"\" width=\"624\" height=\"261\" srcset=\"https:\/\/cloudzeninnovations.com\/dev\/wp-content\/uploads\/2026\/03\/Linux-Service-Monitoring-Architecture-Diagram.jpg 624w, https:\/\/cloudzeninnovations.com\/dev\/wp-content\/uploads\/2026\/03\/Linux-Service-Monitoring-Architecture-Diagram-300x125.jpg 300w\" sizes=\"auto, (max-width: 624px) 100vw, 624px\" \/><\/p>\n<p style=\"text-align: center;\">Illustration diagram \u2014 showing VM, log file, DCR, Log Analytics<\/p>\n<h5>Step 1 \u2013 Generate Service Status Logs on the VM<\/h5>\n<p>We have written a Bash script that checks the status of required services and appends the results to a .log file.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-2844\" src=\"https:\/\/cloudzeninnovations.com\/dev\/wp-content\/uploads\/2026\/03\/Action-Manager-Logs.jpg\" alt=\"\" width=\"624\" height=\"76\" srcset=\"https:\/\/cloudzeninnovations.com\/dev\/wp-content\/uploads\/2026\/03\/Action-Manager-Logs.jpg 624w, https:\/\/cloudzeninnovations.com\/dev\/wp-content\/uploads\/2026\/03\/Action-Manager-Logs-300x37.jpg 300w\" sizes=\"auto, (max-width: 624px) 100vw, 624px\" \/><\/p>\n<p>The script will run on each machine and read the installed services statuses and then generate custom logs with a custom format. We generated the logs to have comma-separated data, with standard log format for ingestion \u2014 server name, service name, status.<\/p>\n<p><strong>VM01, TaskMonitor,Running<\/strong><\/p>\n<p><strong>VM01, Cache Manager, Running<\/strong><\/p>\n<h5>Step 2 \u2013 Configure the Crontab Job<\/h5>\n<p>We added a cron entry to run the script periodically.<br \/>\nThe following example shows the cron Job for Azure Cloud Monitoring under That runs every 3 minutes:<\/p>\n<p><strong>*\/03 * * * * \/root\/home\/user\/az_monitoring\/az_monitoring.sh &gt; \/dev\/null 2&gt;&amp;1<\/strong><\/p>\n<p>PS: It&#8217;s recommended that the script is placed in a private directory or secure location.<\/p>\n<h5>Step 3 \u2013 Set Up the Custom Log File Directory<\/h5>\n<p>Ensure proper log directory\/file permissions.<\/p>\n<p><strong>-rw-r&#8211;r&#8211;. 1 user group 167713 Aug 20 12:18 az_service_status_vm01_20250820.log<\/strong><\/p>\n<h5>Step 4 \u2013 Create the Custom Table in Log Analytics<\/h5>\n<p>Azure automatically creates a table if it doesn\u2019t exist when you configure a DCR, but you can also define a schema in advance.<br \/>\nThe custom table should have the columns: <strong>RawData + TimeGenerated<\/strong>, where RawData will contain the log lines read from the .log file.<br \/>\nTimeGenerated will contain the timestamp at which the log was ingested into the custom table.<br \/>\nExample Table Name: LinuxServiceStatus_CL (_CL is an automatic addition that means Custom Logs)<\/p>\n<h5>Step 5 \u2013 Create a Data Collection Rule (DCR)<\/h5>\n<p>Use Azure Portal, ARM template, or CLI to create the Data Collection Rule.<br \/>\nExample: CLI to create a DCR<\/p>\n<pre><code>  az monitor data-collection rule create \n  --resource-group \n  --name LinuxServiceLogDCR \n  --location \n  --data-flows '[{\"streams\":[\"Custom-LinuxServiceStatus_CL\"],\"destinations\":[\"la-workspace\"]}]' \n  --data-sources '[{\"streams\":[\"Custom-LinuxServiceStatus_CL\"],\"filePatterns\":[\"\/log\/custom\/az_service_status_*.log\"],\"name\":\"linuxServiceLogs\",\"format\":\"text\"}]' \n  --destinations '[{\"type\":\"logAnalytics\",\"workspaceResourceId\":\"\",\"name\":\"la-workspace\"}]'\n<\/code><\/pre>\n<h5>Step 6 \u2013 Link the DCR to Your Azure VM<\/h5>\n<p>Either from portal or CLI:<\/p>\n<pre><code>  az monitor data-collection rule association create\n  --name LinkLinuxLogs\n  --rule-name LinuxServiceLogDCR\n  --resource \n  --description \"Link service status log rule to VM\"\n<\/code><\/pre>\n<h5>Step 7 \u2013 Validate Logs in Log Analytics<\/h5>\n<p>After finishing the previous steps, go to your Log Analytics Workspace, open <strong>Logs <\/strong>from the left blade and run a simple query:<\/p>\n<pre><code>  LinuxServiceStatus_CL\n  | sort by TimeGenerated desc\n<\/code><\/pre>\n<p>You will get a table of logs raw data and its generated timestamps.<\/p>\n<h5>Query Examples: KQL for Insights<\/h5>\n<p>Example query of service availability breakdown \/ detect services That Were Down<\/p>\n<pre><code>\n  LinuxServiceStatus_CL\n  | parse RawData with ComputerName: string \",\" ServiceName: string \",\" ServiceStatus: string\n  | where Status == \"stopped\"\n  | where Server == \"VM01\" and ServiceName == \"Task Monitor\"\n  | project TimeGenerated, Server, ServiceName, Status\n  | order by TimeGenerated desc\n<\/code><\/pre>\n<h5>Bonus: Visualize with Azure Workbook<\/h5>\n<p>Create an Azure Workbook to visualize:<\/p>\n<ul>\n<li>Pie chart of services against statuses<\/li>\n<li>Timechart of service activity<\/li>\n<li>Alerts based on downtime thresholds<\/li>\n<\/ul>\n<h5>Security and Best Practices<\/h5>\n<ul>\n<li>Use managed identities and role-based access control (RBAC).<\/li>\n<li>Avoid writing logs with root privileges.<\/li>\n<li>Use the Azure Monitor Agent (AMA), not legacy OMS agents.<\/li>\n<\/ul>\n<h4>Conclusion<\/h4>\n<p>By combining custom logs with DCRs, you can build a robust and adaptable monitoring pipeline for services running on Azure VMs. This approach ensures high availability, supports scaling needs, and offers rich, query-friendly observability.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In hybrid and cloud-native environments, monitoring custom services and background jobs on VMs is critical for uptime and actions. In this article, we&#8217;ll walk through how to collect service status&hellip; <a href=\"https:\/\/cloudzeninnovations.com\/dev\/linux-service-monitoring-on-azure-vms-with-custom-logs-dcrs\/\" class=\"read-more-link\">Read more<\/a><\/p>\n","protected":false},"author":1,"featured_media":2842,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-2841","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog"],"_links":{"self":[{"href":"https:\/\/cloudzeninnovations.com\/dev\/wp-json\/wp\/v2\/posts\/2841","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cloudzeninnovations.com\/dev\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cloudzeninnovations.com\/dev\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cloudzeninnovations.com\/dev\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/cloudzeninnovations.com\/dev\/wp-json\/wp\/v2\/comments?post=2841"}],"version-history":[{"count":0,"href":"https:\/\/cloudzeninnovations.com\/dev\/wp-json\/wp\/v2\/posts\/2841\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/cloudzeninnovations.com\/dev\/wp-json\/wp\/v2\/media\/2842"}],"wp:attachment":[{"href":"https:\/\/cloudzeninnovations.com\/dev\/wp-json\/wp\/v2\/media?parent=2841"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cloudzeninnovations.com\/dev\/wp-json\/wp\/v2\/categories?post=2841"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cloudzeninnovations.com\/dev\/wp-json\/wp\/v2\/tags?post=2841"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}