{"id":1457,"date":"2009-10-10T14:19:15","date_gmt":"2009-10-10T18:19:15","guid":{"rendered":"http:\/\/www.gubatron.com\/blog\/?p=1457"},"modified":"2009-10-10T14:19:15","modified_gmt":"2009-10-10T18:19:15","slug":"map-commands-to-servers-via-ssh","status":"publish","type":"post","link":"https:\/\/www.gubatron.com\/blog\/map-commands-to-servers-via-ssh\/","title":{"rendered":"Quick N Dirty way to Map Commands to remote servers via ssh"},"content":{"rendered":"<p>You may be running several independent but similar servers at the same time and wasting time by executing commands in all of them one by one.<\/p>\n<p>Wouldn&#8217;t it be nice to send a command to all of them at once? or to monitor all of them at once.<\/p>\n<p>The following script can be used as a building block to more complex automation tasks for a small size set of servers. (If you&#8217;re managing over 50 servers, I&#8217;d probably consider looking a different way to arrange servers (map\/reduce cluster), but if you&#8217;re doing something below that number this might suffice)<\/p>\n<p>[code lang=&#8221;python&#8221;]<br \/>\n#!\/usr\/bin\/python                                                                                                                                                                                                                                                      <\/p>\n<p>#########################################################<br \/>\n# Author: Angel Leon (gubatron@gmail.com) &#8211; October 2009<br \/>\n#<br \/>\n# Invokes a command locally and invokes the same command<br \/>\n# in all machines under the specified username, servers<br \/>\n#<br \/>\n# Requirement: Have a public ssh_key for that user on all<br \/>\n# the other machines so you don&#8217;t have to authenticate<br \/>\n# on all the other machines.<br \/>\n#########################################################<br \/>\nimport sys<br \/>\nimport os<\/p>\n<p># set the username that has access to all the machines here<br \/>\nuser=&#8217;safeuser&#8217;<\/p>\n<p># add all your server names here<br \/>\nservers=[&#8216;server1.mydomain.com&#8217;,&#8217;server2.mydomain.com&#8217;,&#8217;server3.mydomain.com&#8217;]<\/p>\n<p>if __name__ == &quot;__main__&quot;:<br \/>\n  if len(sys.argv) &lt; 2:<br \/>\n    print &quot;Usage: ssh_map_command &lt;cmd&gt;&quot;<br \/>\n    sys.exit(0)<\/p>\n<p>  cmd= &#8216; &#8216;.join(sys.argv[1:])<\/p>\n<p>  #Execute locally first<br \/>\n  print cmd<br \/>\n  os.system(cmd)<\/p>\n<p>  #Execute for all the servers in the list<br \/>\n  for server in servers:<br \/>\n    remote_cmd=&quot;ssh %s@%s %s&quot; % (user,server,cmd)<br \/>\n    print remote_cmd<br \/>\n    os.system(remote_cmd)<br \/>\n    print<br \/>\n[\/code]<\/p>\n<p>Save as ssh_map_command and chmod +x it. <\/p>\n<p><strong>Sample uses<\/strong><br \/>\nCheck the average load of all machines at once (then use output to mitigate high load issues)<br \/>\n[code lang=&#8221;shell&#8221;]$ ssh_map_command uptime[\/code]<\/p>\n<p>Send HUP signal to all your web servers (put it in an alias or other script&#8230; and that&#8217;s how you start building more complex scripts)<br \/>\n[code lang=&#8221;shell&#8221;]$ ssh_map_command ps aux | grep [l]ighttpd | kill -HUP `awk {&#8216;print $2&#8217;}`[\/code]<\/p>\n<p>Check if processes are alive, check memory usage on processes across different machines, <a href=\"http:\/\/en.wikipedia.org\/wiki\/Grep\" target=\"_blank\" rel=\"nofollow\">grep<\/a> remote all logs at once, <a href=\"http:\/\/subversion.tigris.org\/\" target=\"_blank\" rel=\"nofollow\">svn up<\/a> on all machines, <a href=\"http:\/\/samba.anu.edu.au\/rsync\/\" target=\"_blank\" rel=\"nofollow\">rsync<\/a> from one to many, hey, you can even <a href=\"http:\/\/en.wikipedia.org\/wiki\/Tail_%28Unix%29\" target=\"_blank\" rel=\"nofollow\">tail -f<\/a> and grep all the logs at once, you can go nuts with this thing. Depends on what you need to do.<\/p>\n<p><strong>Requirements<\/strong><\/p>\n<ul>\n<li>For convenience you should probably <a href=\"http:\/\/linuxproblem.org\/art_9.html\" target=\"_blank\" rel=\"nofollow\">set up ssh public\/private keys between the main machine and the other machines<\/a> (or they can all trust each other and you can execute on any) so that you can execute commands on all the machines without having to enter passwords.<\/li>\n<li>Put the script on your $PATH.<\/li>\n<li><a href=\"http:\/\/python.org\/\" target=\"_blank\" rel=\"nofollow\">python<\/a><\/li>\n<\/ul>\n<p><strong>Security Advisory<\/strong><br \/>\nMake sure only the desired user has read\/write\/execute access to it and keep your private ssh keys safe (preferably only read and execute for the owner, and no permissions whatsoever to anybody else <strong>chmod 500 ssh_mod_map<\/strong>), if possible change them as often as possible, for it may become a big security whole if an attacker can manage to write code on this script, specially if you have <strong>cronjobs<\/strong> invoking it. Your attacker would only need to change code here to mess up all of your machines.<\/p>\n<p><strong>Disclaimer and Call for Knowledge<\/strong><br \/>\n<img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/farm4.static.flickr.com\/3607\/3677330708_6d68fc4ce0_m.jpg?w=640\" class=\"alignleft\"\/>Please, if someone knows of a standard way to map commands to multiple servers, please let me know in the comment section, in my case I needed a solution and I wrote a quick and dirty python script and tried to secure it as best as I could, by no means I&#8217;m saying that this is the best solution to mapping commands, in fact I believe it might be the least efficient way, however it works good enough for my personal needs.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>You may be running several independent but similar servers at the same time and wasting time by executing commands in all of them one by one. Wouldn&#8217;t it be nice to send a command to all of them at once? or to monitor all of them at once. The following script can be used as [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[15,30,43],"tags":[124,166,183,298,1449,1458,929,1017,1027],"class_list":["post-1457","post","type-post","status-publish","format-standard","hentry","category-code","category-geeklife","category-linux","tag-administration","tag-automation","tag-bash","tag-convenience","tag-linux","tag-python","tag-ssh","tag-tricks","tag-ubuntu"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p5Unzf-nv","jetpack-related-posts":[{"id":1447,"url":"https:\/\/www.gubatron.com\/blog\/ubuntudebian-quick-reference-how-to-change-your-servers-utc-timezone-on-the-command-line\/","url_meta":{"origin":1457,"position":0},"title":"Ubuntu\/Debian Quick Reference: How To Change Your Server&#8217;s UTC Timezone on the command line","author":"gubatron","date":"October 10, 2009","format":false,"excerpt":"Just Type... sudo dpkg-reconfigure tzdata ...and follow the instructions on screen. The process should look something like the following: Select your Region Select a city on your time zone You're done. Tip You can always check the status of your configuration using sudo debconf-show tzdata You could for example map\u2026","rel":"","context":"In &quot;Code&quot;","block_context":{"text":"Code","link":"https:\/\/www.gubatron.com\/blog\/category\/code\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":816,"url":"https:\/\/www.gubatron.com\/blog\/script-to-automatically-detect-and-ban-malicious-ips-that-try-to-brute-force-ssh-accounts\/","url_meta":{"origin":1457,"position":1},"title":"Script to automatically detect and ban malicious IPs that try to brute force SSH accounts","author":"gubatron","date":"May 29, 2008","format":false,"excerpt":"We've noticed that most of our servers have been under heavy attack from random IP addresses to break via SSH. With the help of the last post on how to ban an IP, and the following python script, you'll be able to have a cronjob that runs once or twice\u2026","rel":"","context":"In &quot;Code&quot;","block_context":{"text":"Code","link":"https:\/\/www.gubatron.com\/blog\/category\/code\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1998,"url":"https:\/\/www.gubatron.com\/blog\/startkeychain-bash-utility-to-start-ssh-agent\/","url_meta":{"origin":1457,"position":2},"title":"startKeychain &#8211; bash utility to start ssh-agent","author":"gubatron","date":"June 3, 2010","format":false,"excerpt":"For my (and your) future reference, here's a function to put on your .bashrc or .bash_profile, you can invoke it later at any time to start\/re-start your ssh-agent. [bash] function startKeychain { killall ssh-agent rm ~\/.keychain\/* keychain id_rsa HOSTNAME=`hostname` source ~\/.keychain\/${HOSTNAME}-sh } [\/bash] Then at any time, the \"command\" startKeychain\u2026","rel":"","context":"In &quot;Code&quot;","block_context":{"text":"Code","link":"https:\/\/www.gubatron.com\/blog\/category\/code\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":3150,"url":"https:\/\/www.gubatron.com\/blog\/how-to-add-an-existing-git-repository-to-github\/","url_meta":{"origin":1457,"position":3},"title":"How to add an existing GIT repository to github.","author":"gubatron","date":"August 31, 2013","format":false,"excerpt":"Most of the times, it makes more sense to start working on something that slowly transforms into the beginning of a project that deserves to be on github. This post is about creating a local repository and putting it on github. 1. First we must convert the main local folder\u2026","rel":"","context":"In &quot;Code&quot;","block_context":{"text":"Code","link":"https:\/\/www.gubatron.com\/blog\/category\/code\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1419,"url":"https:\/\/www.gubatron.com\/blog\/check-the-top-10-linux-commands-you-cant-live-without\/","url_meta":{"origin":1457,"position":4},"title":"Check the Top 10 Linux Commands you can&#8217;t live without","author":"gubatron","date":"September 28, 2009","format":false,"excerpt":"Type the following on your cmd line (or make into an alias) cat ~\/.bash_history | sort | uniq -c | sort -r | head In my case they are (for this week) ls fg svnSync (script I created) stats_fetch; stats_display (other scripts) cd crontab -e ps aux | grep ssh_map_command\u2026","rel":"","context":"In &quot;Code&quot;","block_context":{"text":"Code","link":"https:\/\/www.gubatron.com\/blog\/category\/code\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":2767,"url":"https:\/\/www.gubatron.com\/blog\/ubuntu-packages-for-a-kick-ass-web-server\/","url_meta":{"origin":1457,"position":5},"title":"ubuntu packages for a kick ass web server","author":"gubatron","date":"September 7, 2012","format":false,"excerpt":"Copy and paste the following list on a file, say \"packages.txt\". To install all just do: sudo apt-get install $(cat packages.txt) accountsservice acpid adduser ant ant-optional apache2-utils apparmor apport apport-symptoms apt apt-transport-https apt-utils apt-xapian-index aptitude at base-files base-passwd bash bash-completion bc bind9-host bsdmainutils bsdutils busybox-initramfs busybox-static byobu bzip2 ca-certificates ca-certificates-java\u2026","rel":"","context":"In &quot;Code&quot;","block_context":{"text":"Code","link":"https:\/\/www.gubatron.com\/blog\/category\/code\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"_links":{"self":[{"href":"https:\/\/www.gubatron.com\/blog\/wp-json\/wp\/v2\/posts\/1457","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.gubatron.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.gubatron.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.gubatron.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.gubatron.com\/blog\/wp-json\/wp\/v2\/comments?post=1457"}],"version-history":[{"count":0,"href":"https:\/\/www.gubatron.com\/blog\/wp-json\/wp\/v2\/posts\/1457\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.gubatron.com\/blog\/wp-json\/wp\/v2\/media?parent=1457"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.gubatron.com\/blog\/wp-json\/wp\/v2\/categories?post=1457"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.gubatron.com\/blog\/wp-json\/wp\/v2\/tags?post=1457"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}