{"id":1973,"date":"2023-10-09T20:50:47","date_gmt":"2023-10-09T20:50:47","guid":{"rendered":"https:\/\/hostingspell.com\/blog\/?p=1973"},"modified":"2023-10-09T22:26:17","modified_gmt":"2023-10-09T22:26:17","slug":"automating-bulk-account-termination-in-cpanel-whm-with-a-bash-script","status":"publish","type":"post","link":"https:\/\/blog.hostingspell.com\/automating-bulk-account-termination-in-cpanel-whm-with-a-bash-script\/","title":{"rendered":"Automating Bulk Account Termination in cPanel\/WHM with a Bash Script"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Creating a few scripts showcasing the use case for sysadmins and providing deployment and automation steps on this great idea. Here&#8217;s a template for your ideal Shell script.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p class=\"wp-block-paragraph\">In shared hosting environments, managing user accounts efficiently is crucial. Whether you&#8217;re a web hosting provider or a system administrator, automating tasks like account termination can save you time and effort. In this article, we&#8217;ll introduce you to a Bash script that automates account termination in cPanel\/WHM. We&#8217;ll also walk you through the steps to deploy and automate this script using cron jobs.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Introduction<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The provided Bash script automates the process of account termination in cPanel\/WHM servers. It&#8217;s designed to target root-owned accounts, ensuring that reseller-owned accounts remain untouched. This script is particularly useful if you need to clean up unused or overdue accounts efficiently.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Prerequisites<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Before you proceed, ensure the following prerequisites are met:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>You have SSH access to your cPanel\/WHM server.<\/li>\n\n\n\n<li>You have root or sudo access to execute commands.<\/li>\n\n\n\n<li>The script only deletes suspended cPanel accounts by default.<\/li>\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h4 class=\"wp-block-heading\">Script type 1: Auto delete all suspended cPanel accounts in &#8216;Overdue on Payment&#8217; reason that failed to be deleted by WHMCS cron run (Excludes reseller and their accounts)<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>#!\/bin\/bash\n\n# Set the suspension reason\nSUSPENSION_REASON=\"Overdue on Payment\"\n\n# Create a log file with the current date and time\ncurrent_datetime=$(date +\"%Y%m%d%H%M%S\")\nlog_file=\"auto-terminate-log-$current_datetime.txt\"\n\n# Initialize counters\nroot_owned_deleted=0\nfailed_to_delete=0\n\n# Start timestamp\nstart_time=$(date +%s)\n\n# Interrupt handler\nfunction cleanup() {\n    end_time=$(date +%s)\n    execution_time=$((end_time - start_time))\n\n    echo \"\"\n    echo \"Deletion process completed.\"\n    echo \"$root_owned_deleted root-owned accounts deleted.\"\n    echo \"$failed_to_delete accounts failed to delete.\"\n    echo \"Execution time: $execution_time seconds.\"\n    echo \"Log saved in $log_file.\"\n    exit\n}\n\ntrap cleanup INT\n\n# Create or append to the log file\ntouch \"$log_file\"\n\n# Display a header\necho \"Auto-Terminate Script\"\necho \"Suspension Reason: $SUSPENSION_REASON\"\necho \"----------------------------------\"\n\n# List all suspended accounts and show ownership type\necho \"Suspended Accounts:\"\nfor account_file in \/var\/cpanel\/suspended\/*; do\n    # Extract the account username from the file name\n    account=$(basename \"$account_file\")\n\n    # Use 'whmapi1' to get account ownership information\n    account_info=$(whmapi1 accountsummary user=\"$account\")\n\n    # Check if the line 'owner: root' is present in the response\n    if &#91;&#91; \"$account_info\" =~ 'owner: root' ]]; then\n        # Display a real-time message\n        echo \"Deleting root-owned account: $account...\"\n\n        # Use 'yes' command to provide a default answer of 'y' (yes)\n        yes | \/usr\/local\/cpanel\/scripts\/removeacct \"$account\"\n\n        # Check if the deletion was successful\n        if &#91; $? -eq 0 ]; then\n            # Increment the deleted count for root-owned accounts\n            ((root_owned_deleted++))\n            # Log the deleted account\n            echo \"Root-owned account $account deleted due to suspension reason '$SUSPENSION_REASON'.\" &gt;&gt; \"$log_file\"\n        else\n            # Increment the failed count\n            ((failed_to_delete++))\n            echo \"Failed to delete root-owned account: $account\" &gt;&gt; \"$log_file\"\n        fi\n    else\n        # Account is reseller-owned, do not delete\n        echo \"Skipping reseller-owned account: $account\" &gt;&gt; \"$log_file\"\n    fi\ndone\n\n# Cleanup and exit\ncleanup\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Script Overview<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The Bash script performs the following tasks:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Lists all suspended accounts and categorizes them as either root-owned or reseller-owned.<\/li>\n\n\n\n<li>Waits for 10 seconds before proceeding to account termination.<\/li>\n\n\n\n<li>Deletes root-owned accounts only if the suspension reason is &#8220;Overdue on Payment.&#8221;<\/li>\n\n\n\n<li>Logs the deletion process, including successful deletions and failures.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Deployment Steps<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Follow these steps to deploy the script on your cPanel\/WHM server:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Create a Bash Script File<\/strong>: Create a new file on your server  <code>nano auto-cp-terminate.sh<\/code><\/li>\n\n\n\n<li><strong>Edit the Script<\/strong>: Copy and paste the script content from the provided Bash script into <code>auto-cp-terminate.sh<\/code><\/li>\n\n\n\n<li><strong>Make the Script Executable<\/strong>: Run the following command to make the script executable: <code>chmod +x auto-cp-terminate.sh<\/code><\/li>\n\n\n\n<li><strong>Run the Script<\/strong>: Execute the script using the following command: <code>.\/auto-cp-terminate.sh<\/code> The script will list suspended accounts, determine their ownership, and delete root-owned accounts with the &#8220;Overdue on Payment&#8221; suspension reason.<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">Automating Account Termination<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">To automate the account termination process, you can use a cron job. Here&#8217;s how to set it up:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Edit the crontab file<\/strong>: Run the following command to edit your user&#8217;s crontab: <code>crontab -e<\/code><\/li>\n\n\n\n<li><strong>Add a Cron Job<\/strong>: To run the script daily at a specific time, add the following line to your crontab: <code>0 0 * * * \/path\/to\/auto-cp-terminate.sh<\/code> Replace <code>\/path\/to\/auto-cp-terminate.sh<\/code> with the actual path to your script file.<\/li>\n\n\n\n<li><strong>Save and Exit<\/strong>: Save the changes and exit the text editor.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Now, the script will run automatically at the specified time every day, helping you maintain your server&#8217;s account hygiene.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Script type 2: Auto delete all suspended cPanel accounts with Account Owner Name and Suspension Reason as parameter<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>#!\/bin\/bash\r\n\r\n# Function to check the owner of a cPanel account and suspend if the reason matches\r\nfunction check_account_owner_and_suspend() {\r\n    local username=\"$1\"\r\n    local owner_to_check=\"$2\"\r\n    local suspension_reason=\"$3\"\r\n    local account_info=$(whmapi1 accountsummary user=\"$username\")\r\n\r\n    # Check if the line 'owner: $owner_to_check' is present in the response\r\n    if &#91;&#91; \"$account_info\" =~ \"owner: $owner_to_check\" ]]; then\r\n        echo \"Processing account: $username, Owner: $owner_to_check, Suspension Reason: $suspension_reason\"\r\n\r\n        # Check if the suspension reason matches the specified reason\r\n        if grep -q \"$suspension_reason\" \"\/var\/cpanel\/suspended\/$username\"; then\r\n            echo \"Deleting account: $username...\"\r\n            yes | \/usr\/local\/cpanel\/scripts\/removeacct \"$username\"\r\n            \r\n            # Check if the deletion was successful\r\n            if &#91; $? -eq 0 ]; then\r\n                echo \"Account $username deleted due to suspension reason '$suspension_reason'.\" >> \"$log_file\"\r\n                ((deleted_count++))\r\n            else\r\n                echo \"Failed to delete account: $username\"\r\n                echo \"Failed to delete account: $username, Owner: $owner_to_check, Suspension Reason: $suspension_reason\" >> \"$log_file\"\r\n            fi\r\n        fi\r\n    fi\r\n}\r\n\r\n# Create a log file with the current date and time\r\ncurrent_datetime=$(date +\"%Y%m%d%H%M%S\")\r\nlog_file=\"auto-terminate-log-$current_datetime.txt\"\r\n\r\n# Initialize a counter for deleted accounts\r\ndeleted_count=0\r\n\r\n# Prompt the user for the owner's name\r\necho -n \"Enter the owner's name: \"\r\nread owner_name\r\n\r\n# Prompt the user for the suspension reason\r\necho -n \"Enter the suspension reason: \"\r\nread suspension_reason\r\n\r\n# Loop through the suspended account files\r\nfor account_file in \/var\/cpanel\/suspended\/*; do\r\n    # Extract the account username from the file name\r\n    account=$(basename \"$account_file\")\r\n\r\n    # Call the function to check the account owner and suspend if needed\r\n    check_account_owner_and_suspend \"$account\" \"$owner_name\" \"$suspension_reason\"\r\ndone\r\n\r\n# Display the total number of deleted accounts and a completion message\r\necho \"Deletion process completed. $deleted_count accounts deleted. Log saved in $log_file.\"\r\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Above mentioned script will delete all the Owner&#8217;s accounts for the given Reason.<\/p>\n\n\n\n<ul class=\"wp-block-list\"><\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">In this script:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>It prompts the user to enter the owner&#8217;s name and suspension reason.<\/li>\n\n\n\n<li>It checks if the suspension reason and owner&#8217;s name match before deleting an account.<\/li>\n\n\n\n<li>It logs the deletion process, including successful deletions and failures, with the owner&#8217;s name and suspension reason.<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">Script type 3: Auto delete all suspended cPanel accounts (Also, root and reseller)<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>#!\/bin\/bash\n\n# Set the suspension reason\nSUSPENSION_REASON=\"Overdue on Payment\"\n\n# Create a log file with the current date and time\ncurrent_datetime=$(date +\"%Y%m%d%H%M%S\")\nlog_file=\"auto-terminate-log-$current_datetime.txt\"\n\n# Initialize a counter for deleted accounts\ndeleted_count=0\n\n# Loop through the suspended account files\nfor account_file in \/var\/cpanel\/suspended\/*; do\n    # Extract the account username from the file name\n    account=$(basename \"$account_file\")\n\n    # Check if the suspension reason matches the specified reason\n    if grep -q \"$SUSPENSION_REASON\" \"$account_file\"; then\n        # Display a real-time message\n        echo \"Deleting account: $account...\"\n\n        # Use 'yes' command to provide a default answer of 'y' (yes)\n        yes | \/usr\/local\/cpanel\/scripts\/removeacct \"$account\"\n\n        # Check if the deletion was successful\n        if &#91; $? -eq 0 ]; then\n            # Increment the deleted count\n            ((deleted_count++))\n            # Log the deleted account\n            echo \"Account $account deleted due to suspension reason '$SUSPENSION_REASON'.\" &gt;&gt; \"$log_file\"\n        else\n            echo \"Failed to delete account: $account\"\n        fi\n    fi\ndone\n\n# Display the total number of deleted accounts and a completion message\necho \"Deletion process completed. $deleted_count accounts deleted. Log saved in $log_file.\"<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Above mentioned script, type 2 will delete all suspended cPanel accounts once started.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Conclusion<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Automating account termination in cPanel\/WHM can streamline your server management tasks. With the Bash script provided in this article, you can efficiently remove root-owned accounts with overdue payments while leaving reseller-owned accounts untouched. By setting up a cron job, you can automate this process, saving time and ensuring a well-maintained hosting environment.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Feel free to customize the script and cron job schedule to fit your specific needs. Managing your server has never been easier with this automated solution.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p class=\"wp-block-paragraph\">You can publish this article on your WordPress website, making sure to format it as needed and add any additional details or images you think would be helpful.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Creating a few scripts showcasing the use case for sysadmins and providing deployment and automation steps on this great idea. Here&#8217;s a template for your ideal Shell script. In shared hosting environments, managing user accounts efficiently is crucial. Whether you&#8217;re a web hosting provider or a system administrator, automating tasks like account termination can save [&hellip;]<\/p>\n","protected":false},"author":9,"featured_media":1647,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_uag_custom_page_level_css":"","_genesis_hide_title":false,"_genesis_hide_breadcrumbs":false,"_genesis_hide_singular_image":false,"_genesis_hide_footer_widgets":false,"_genesis_custom_body_class":"","_genesis_custom_post_class":"","_genesis_layout":"","footnotes":""},"categories":[82],"tags":[],"class_list":["post-1973","post","type-post","status-publish","format-standard","has-post-thumbnail","category-shell-scripts","entry"],"featured_image_src":"https:\/\/blog.hostingspell.com\/wp-content\/uploads\/2021\/03\/hspl-blog-default.png","featured_image_src_square":"https:\/\/blog.hostingspell.com\/wp-content\/uploads\/2021\/03\/hspl-blog-default.png","author_info":{"display_name":"C01R3","author_link":"https:\/\/blog.hostingspell.com\/author\/c01r3\/"},"uagb_featured_image_src":{"full":["https:\/\/blog.hostingspell.com\/wp-content\/uploads\/2021\/03\/hspl-blog-default.png",580,290,false],"thumbnail":["https:\/\/blog.hostingspell.com\/wp-content\/uploads\/2021\/03\/hspl-blog-default-150x150.png",150,150,true],"medium":["https:\/\/blog.hostingspell.com\/wp-content\/uploads\/2021\/03\/hspl-blog-default-300x150.png",300,150,true],"medium_large":["https:\/\/blog.hostingspell.com\/wp-content\/uploads\/2021\/03\/hspl-blog-default.png",580,290,false],"large":["https:\/\/blog.hostingspell.com\/wp-content\/uploads\/2021\/03\/hspl-blog-default.png",580,290,false],"1536x1536":["https:\/\/blog.hostingspell.com\/wp-content\/uploads\/2021\/03\/hspl-blog-default.png",580,290,false],"2048x2048":["https:\/\/blog.hostingspell.com\/wp-content\/uploads\/2021\/03\/hspl-blog-default.png",580,290,false],"single-featured-image":["https:\/\/blog.hostingspell.com\/wp-content\/uploads\/2021\/03\/hspl-blog-default.png",580,290,false],"blog-featured-image":["https:\/\/blog.hostingspell.com\/wp-content\/uploads\/2021\/03\/hspl-blog-default.png",580,290,false],"home-featured":["https:\/\/blog.hostingspell.com\/wp-content\/uploads\/2021\/03\/hspl-blog-default-380x290.png",380,290,true],"ab-block-post-grid-landscape":["https:\/\/blog.hostingspell.com\/wp-content\/uploads\/2021\/03\/hspl-blog-default.png",580,290,false],"ab-block-post-grid-square":["https:\/\/blog.hostingspell.com\/wp-content\/uploads\/2021\/03\/hspl-blog-default.png",580,290,false],"author-pro-image":["https:\/\/blog.hostingspell.com\/wp-content\/uploads\/2021\/03\/hspl-blog-default.png",360,180,false],"gb-block-post-grid-landscape":["https:\/\/blog.hostingspell.com\/wp-content\/uploads\/2021\/03\/hspl-blog-default.png",580,290,false],"gb-block-post-grid-square":["https:\/\/blog.hostingspell.com\/wp-content\/uploads\/2021\/03\/hspl-blog-default.png",580,290,false]},"uagb_author_info":{"display_name":"C01R3","author_link":"https:\/\/blog.hostingspell.com\/author\/c01r3\/"},"uagb_comment_info":0,"uagb_excerpt":"Creating a few scripts showcasing the use case for sysadmins and providing deployment and automation steps on this great idea. Here&#8217;s a template for your ideal Shell script. In shared hosting environments, managing user accounts efficiently is crucial. Whether you&#8217;re a web hosting provider or a system administrator, automating tasks like account termination can save&hellip;","_links":{"self":[{"href":"https:\/\/blog.hostingspell.com\/wp-json\/wp\/v2\/posts\/1973","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.hostingspell.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.hostingspell.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.hostingspell.com\/wp-json\/wp\/v2\/users\/9"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.hostingspell.com\/wp-json\/wp\/v2\/comments?post=1973"}],"version-history":[{"count":6,"href":"https:\/\/blog.hostingspell.com\/wp-json\/wp\/v2\/posts\/1973\/revisions"}],"predecessor-version":[{"id":1982,"href":"https:\/\/blog.hostingspell.com\/wp-json\/wp\/v2\/posts\/1973\/revisions\/1982"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.hostingspell.com\/wp-json\/wp\/v2\/media\/1647"}],"wp:attachment":[{"href":"https:\/\/blog.hostingspell.com\/wp-json\/wp\/v2\/media?parent=1973"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.hostingspell.com\/wp-json\/wp\/v2\/categories?post=1973"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.hostingspell.com\/wp-json\/wp\/v2\/tags?post=1973"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}