{"id":18513974,"url":"https://github.com/daddye/do","last_synced_at":"2025-10-10T17:10:30.916Z","repository":{"id":62557340,"uuid":"2176044","full_name":"DAddYE/do","owner":"DAddYE","description":"DO - IT! is a thin framework useful to manage remote servers through ssh.","archived":false,"fork":false,"pushed_at":"2014-08-26T18:04:07.000Z","size":182,"stargazers_count":167,"open_issues_count":1,"forks_count":8,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-10-07T15:58:28.829Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://github.com/DAddYE/do","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/DAddYE.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGES.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2011-08-08T21:33:41.000Z","updated_at":"2024-04-29T02:02:40.000Z","dependencies_parsed_at":"2022-11-03T06:30:31.063Z","dependency_job_id":null,"html_url":"https://github.com/DAddYE/do","commit_stats":null,"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"purl":"pkg:github/DAddYE/do","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DAddYE%2Fdo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DAddYE%2Fdo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DAddYE%2Fdo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DAddYE%2Fdo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DAddYE","download_url":"https://codeload.github.com/DAddYE/do/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DAddYE%2Fdo/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279004815,"owners_count":26083783,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-10T02:00:06.843Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-06T15:41:35.081Z","updated_at":"2025-10-10T17:10:30.900Z","avatar_url":"https://github.com/DAddYE.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# DO .. it! - Framework Toolkit for Sysadmin\n\nDO is a thin framework useful to manage remote servers through ssh.\n\nThere are many other alternatives, one of them is\n[capistrano](https://github.com/capistrano/capistrano).\n\nSo why another one? Basically I need:\n\n* easy creation of my recipes\n* see perfectly what's happening on my remote servers\n* highly focus on smart actions, upload, download, sudo, replace.\n* manage easily more than one server at same time\n* a use same syntax to manage local tasks\n\nWhat really is *DO* ?\n\n* somewhat like brew\n* somewhat like rake\n* somewhat like capistrano\n\nAll together mixed to make your life easier.\n\nAs mentioned before do is a fun mix of capistrano, rake, thor and brew.\n\nWith *DO* you are be able to do easily common task on your local or remote machine.\nThe aim of *DO* is to become the unique and universal tool language that permit you to make\nyour own _brew_, _apt-get_ or _yum_ package, same syntax for all your machine.\n\n## DO - Installation and Setup\n\n```sh\n$ sudo gem install do\n$ doit download # download a new recipe with --url=\n$ doit setup    # setup a working home directory\n$ doit version  # show version number\n$ doit list     # show task list\n$ doit help     # show help message\n```\n\nNow you can edit your `~/.do/dorc` adding your **servers** or **plugins**.\n\n## DO - Files\n\nThere are different ways to generate **DO** tasks, you can:\n\n* Create a file called `Do` or `Dofile` in your project directory (_project wide_)\n* Create `*.rake` files in `~/.do` directory (_system wide_)\n* Create a file called `dorc` in `~/.do` directory (_system wide_)\n\nYou can change the *DO* home directory (default: `~/.do`) with these\ncommands:\n\n```\nDO_PATH='/my/new/.do/path'\nENV['DO_PATH']='/my/new/.do/path'\nexport DO_PATH='/my/new/.do/path'\n```\n\nIn this guide we assume that your `DO_PATH` is `~/.do`.\n\n## DO - Features\n\n* Easily server logging\n* SSH connections\n* SFTP connections (upload and download)\n* run cmd (we handle also with input)\n* shortcuts (exist?, read, replace, append etc...)\n\nCode is much better:\n\n```rb\nserver = DO::Server.new('srv1', 'srv1.domain.local', 'root', :key =\u003e %w[srv1.pem]\n\nserver.run 'uname'\n# root@srv1 ~ # uname\n# Linux\n\nserver.run 'uname', '-a'\n# root@srv1 ~ # uname -a\n# Linux srv1.lipsiasoft.net 2.6.18-194.32.1.el5  x86_64 x86_64 x86_64 GNU/Linux\n\nserver.run 'mysqladmin -u root -p password \"oldone\"', 'newpassword'\n# root@srv1 ~ # mysqladmin -u root -p password 'oldone'\n# Enter password: oldone\n# mysqladmin: connect to server at 'localhost' failed\n# error: 'Access denied for user 'root'@'localhost' (using password: YES)'\n\nserver.exist?('~/.ssh')\n# root@srv1 ~ # test -e ~/.ssh \u0026\u0026 echo True\n# =\u003e true\n\nserver.read('/etc/redhat-release')\n# root@srv1 ~ # cat /etc/redhat-release\n# =\u003e \"CentOS release 5.5 (Final)\"\n\nserver.upload '/tmp/file', '/tmp/foo'\n# root@srv1 ~ # upload from '/tmp/file' to '/tmp/foo'\n\nserver.download '/tmp/foo', '/tmp/file2'\n# root@srv1 ~ # download from '/tmp/foo' to '/tmp/file2'\n\nserver.replace :all, 'new content', '/tmp/file'\n# root@srv1 ~ # replace all in '/tmp/foo'\n\nserver.read('/tmp/foo')\n# root@srv1 ~ # cat /tmp/foo\n# =\u003e \"new content\"\n\nserver.replace /content$/, 'changed content', '/tmp/foo'\n# root@srv1 ~ # replace /content$/ in '/tmp/foo'\n\nserver.read('/tmp/foo')\n# root@srv1 ~ # cat /tmp/foo\n# =\u003e \"new changed content\"\n\nserver.append('appended', '/tmp/foo')\n# root@srv1 ~ # append to 'bottom' in '/tmp/foo'\n\nserver.read('/tmp/foo')\n# root@srv1 ~ # cat /tmp/foo\n# =\u003e \"new changed contentappended\"\n\nserver.append('---', '/tmp/foo', :top)\n# root@srv1 ~ # append to 'top' in '/tmp/foo'\n\nserver.read('/tmp/foo')\n# root@srv1 ~ # cat /tmp/foo\n# =\u003e \"---new changed contentappended\"\n\nserver.ask \"Please choose\"\n# root@srv1 ~ # Please choose: foo\n# =\u003e \"foo\"\n\nserver.yes? \"Do you want to proceed\"\n# root@srv1 ~ # Do you want to proceed? (y/n): y\n# =\u003e 0\n\nserver.wait\n# Press ENTER to continue...\n```\n\n## DO - Plugins\n\nDO, support plugins, you can manually add new one in your `~/.do/dorc`\nwith a simple line:\n\n```rb\nplugin :vim, 'https://raw.github.com/DAddYE/.do/master/vim.rake'\n```\n\nHowever we have a `doit` command for that:\n\n```sh\n$ doit download --url https://raw.github.com/DAddYE/.do/master/vim.rake\n```\n\nThis command add for you a new line in your `~/.do/dorc` and perform:\n\n```sh\n$ doit plugin:vim\n```\n\nwhich download and install in your `~/.do/dorc` directory a new rake\nfile.\n\nOnce this happen you are be able to see new tasks:\n\n```sh\n$ doit list\n\ndoit plugin:vim                  # install vim plugin\ndoit setup                       # setup a working home directory\ndoit vim:configure               # configure with a janus custom template\ndoit vim:install                 # install vim with python and ruby support\n```\n\n## Scenario and examples\n\nI'm porting my custom recipes to *DO*, you can find my dot files\n[here](https://github.com/daddye/.do).\n\nHere servers definitions:\n\n```rb\n# ~/.do/dorc\nkeys = %w(/keys/master.pem /keys/instances.pem /keys/stage.pem)\nserver :sho0, 'sho0.lipsiasoft.biz', 'root', :keys =\u003e keys\nserver :srv0, 'srv0.lipsiasoft.biz', 'root', :keys =\u003e keys\nserver :srv1, 'srv1.lipsiasoft.biz', 'root', :keys =\u003e keys\nserver :srv2, 'srv2.lipsiasoft.biz', 'root', :keys =\u003e keys\n```\n\nI've also some recipes in my `~/.do` path:\n\n```rb\n# ~/.do/configure.rake\nnamespace :configure\n  desc \"upgrade rubygems and install useful gems\"\n  task :gems =\u003e :ree, :in =\u003e :web do\n    run \"gem update --system\" if yes?(\"Do you want to update rubygems?\")\n    run \"gem install rake\"\n    run \"gem install highline\"\n    run \"gem install bundler\"\n    run \"ln -s /opt/ruby-enterprise/bin/bundle /usr/bin/bundle\" unless exist?(\"/usr/bin/bundle\")\n  end\n\n  desc \"create motd for each server\"\n  task :motd, :in =\u003e :remote do\n    replace :all, \"Hey boss! Welcome to the \\e[1m#{name}\\e[0m of LipsiaSOFT s.r.l.\\n\", \"/etc/motd\"\n  end\n\n  desc \"redirect emails to a real account\"\n  task :root_emails, :in =\u003e :remote do\n    append \"\\nroot: servers@lipsiasoft.com\", \"/etc/aliases\"\n    run \"newaliases\"\n  end\n\n  desc \"mysql basic configuration\"\n  task :mysql =\u003e :yum, :in =\u003e :remote do\n    run \"yum install mysql-server mysql mysql-devel -y\"\n    run \"chkconfig --level 2345 mysqld on\"\n    run \"service mysqld restart\"\n    pwd = ask \"Tell me the password for mysql\"\n    run \"mysqladmin -u root -p password '#{pwd}'\", :input =\u003e \"\\n\"\n    run \"service mysqld restart\"\n    run \"ln -fs /var/lib/mysql/mysql.sock /tmp/mysql.sock\"\n  end\n...\n```\n\nI call these task with:\n\n```sh\n$ doit configure:gems\n$ doit configure:motd\n$ doit configure:mysql\n```\n\n**NOTE** like rake tasks you are be able to add prerequisites to\nany task, ex:\n\n```rb\ntask :mysql =\u003e :yum, :in =\u003e :remote do; ...; end\n```\n\nThat's are some local tasks:\n\n```rb\nnamespace :l do\n  task :setup do\n    name = File.basename(File.expand_path('.'))\n    exit unless yes?('Do you want to setup \"%s\"?' % name)\n    srv = nil\n\n    until servers.map(\u0026:name).include?(srv)\n      srv = ask(\"Which server do you want to use (%s)\" % servers.map(\u0026:name).join(\", \")).to_sym\n    end\n\n    if File.exist?('.git')\n      exit unless yes?('Project \"%s\" has already a working repo, do you want remove it?' % name)\n      run 'rm -rf .git'\n    end\n\n    run 'git init'\n    run 'git remote add origin git@lipsiasoft.biz:/%s.git' % name\n    run_task('l:commit') if yes?(\"Are you ready to commit it, database, config etc is correct?\")\n  end\n\n  task :commit do\n    run 'git add .'\n    run 'git commit -a'\n    run 'git push origin master'\n  end\nend\n```\n\nWhen I need to setup a new project:\n\n``` sh\n$ doit l:setup\n$ doit l:commit # to make a fast commit and push\n```\n\nAs you can see, define remote and local task, is simple like making\nstandard rake tasks. *DO* extend `Rake`.\n\n## DO - Filtering\n\nSometimes you want to perform a task only on some servers:\n\n```sh\n$ doit configure:new --srv1 # apply recipes only on srv1\n$ doit configure:new --no-srv1 # apply recipes to all except srv1\n```\n\n## DO - Output (Awesome...)\n\nWhat I really wanted was a great understandable, colored output that clarify\nme what's happen on my remote servers.\n\nHere a example output of my tasks:\n\n```\nroot@sho0 ~ # touch /root/.bashrc\nroot@sho0 ~ # replace all in '/root/.bashrc'\nroot@sho0 ~ # replace all in '/etc/motd'\nroot@sho0 ~ # replace /HOSTNAME=.*/ in '/etc/sysconfig/network'\nroot@sho0 ~ # chmod +w /etc/sudoers\nroot@sho0 ~ # replace /^Defaults    requiretty/ in '/etc/sudoers'\nroot@sho0 ~ # chkconfig --level 2345 sendmail on\nroot@sho0 ~ # chkconfig --level 2345 mysqld on\nroot@sho0 ~ # service sendmail restart\nShutting down sm-client: [  OK  ]\nShutting down sendmail: [  OK  ]\nStarting sendmail: [  OK  ]\nStarting sm-client: [  OK  ]\nroot@sho0 ~ # service mysqld restart\nStopping mysqld:  [  OK  ]\nStarting mysqld:  [  OK  ]\nroot@sho0 ~ # Tell me the password for mysql: xx\nroot@sho0 ~ # mysqladmin -u root -p password xx'\nEnter password: xx\nmysqladmin: connect to server at 'localhost' failed\nerror: 'Access denied for user 'root'@'localhost' (using password: NO)'\nroot@sho0 ~ # service mysqld restart\nStopping mysqld:  [  OK  ]\nStarting mysqld:  [  OK  ]\nroot@sho0 ~ # ln -fs /var/lib/mysql/mysql.sock /tmp/mysql.sock\n```\n\n## Copyright\n\nCopyright (C) 2011 Davide D'Agostino -\n[@daddye](http://twitter.com/daddye)\n\nPermission is hereby granted, free of charge, to any person obtaining a\ncopy of this software and\nassociated documentation files (the “Software”), to deal in the Software\nwithout restriction, including without\nlimitation the rights to use, copy, modify, merge, publish, distribute,\nsublicense, and/or sell copies of the Software,\nand to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included\nin all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS\nOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM,\nDAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\nOTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdaddye%2Fdo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdaddye%2Fdo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdaddye%2Fdo/lists"}