One place for hosting & domains

      Commands

      How To Use docker exec to Run Commands in a Docker Container


      Introduction

      Docker is a containerization tool that helps developers create and manage portable, consistent Linux containers.

      When developing or deploying containers you’ll often need to look inside a running container to inspect its current state or debug a problem. To this end, Docker provides the docker exec command to run programs in containers that are already running.

      In this tutorial we will learn about the docker exec command and how to use it to run commands and get an interactive shell in a running Docker container.

      Prerequisites

      This tutorial assumes you already have Docker installed, and your user has permission to run docker. If you need to run docker as the root user, please remember to prepend sudo to the commands in this tutorial.

      For more information on using Docker without sudo access, please see the Executing the Docker Command Without Sudo section of our How To Install Docker tutorial.

      Starting a Test Container

      To use the docker exec command, you will need a running Docker container. If you don’t already have a container, start a test container with the following docker run command:

      • docker run -d --name container-name alpine watch "date >> /var/log/date.log"

      This command creates a new Docker container from the official alpine image. This is a popular Linux container image that uses Alpine Linux, a lightweight, minimal Linux distribution.

      We use the -d flag to detach the container from our terminal and run it in the background. --name container-name will name the container container-name. You could choose any name you like here, or leave this off entirely to have Docker automatically generate a unique name for the new container.

      Next we have alpine, which specifies the image we want to use for the container.

      And finally we have watch "date >> /var/log/date.log". This is the command we want to run in the container. watch will repeatedly run the command you give it, every two seconds by default. The command that watch will run in this case is date >> /var/log/date.log. date prints the current date and time, like this:

      Output

      • Fri Jul 23 14:57:05 UTC 2021

      The >> /var/log/date.log portion of the command redirects the output from date and appends it to the file /var/log/date.log. Every two seconds a new line will be appended to the file, and after a few seconds it will look something like this:

      Output

      Fri Jul 23 15:00:26 UTC 2021 Fri Jul 23 15:00:28 UTC 2021 Fri Jul 23 15:00:30 UTC 2021 Fri Jul 23 15:00:32 UTC 2021 Fri Jul 23 15:00:34 UTC 2021

      In the next step we’ll learn how to find the names of Docker containers. This will be useful if you already have a container you’re targeting, but you’re not sure what its name is.

      Finding the Name of a Docker Container

      We’ll need to provide docker exec with the name (or container ID) of the container we want to work with. We can find this information using the docker ps command:

      This command lists all of the Docker containers running on the server, and provides some high-level information about them:

      Output

      CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 76aded7112d4 alpine "watch 'date >> /var…" 11 seconds ago Up 10 seconds container-name

      In this example, the container ID and name are highlighted. You may use either to tell docker exec which container to use.

      If you’d like to rename your container, use the docker rename command:

      • docker rename container-name new-name

      Next, we’ll run through several examples of using docker exec to execute commands in a running Docker container.

      Running an Interactive Shell in a Docker Container

      If you need to start an interactive shell inside a Docker Container, perhaps to explore the filesystem or debug running processes, use docker exec with the -i and -t flags.

      The -i flag keeps input open to the container, and the -t flag creates a pseudo-terminal that the shell can attach to. These flags can be combined like this:

      • docker exec -it container-name sh

      This will run the sh shell in the specified container, giving you a basic shell prompt. To exit back out of the container, type exit then press ENTER:

      If your container image includes a more advanced shell such as bash, you could replace sh with bash above.

      Running a Non-interactive Command in a Docker Container

      If you need to run a command inside a running Docker container, but don’t need any interactivity, use the docker exec command without any flags:

      • docker exec container-name tail /var/log/date.log

      This command will run tail /var/log/date.log on the container-name container, and output the results. By default the tail command will print out the last ten lines of a file. If you’re running the demo container we set up in the first section, you will see something like this:

      Output

      Mon Jul 26 14:39:33 UTC 2021 Mon Jul 26 14:39:35 UTC 2021 Mon Jul 26 14:39:37 UTC 2021 Mon Jul 26 14:39:39 UTC 2021 Mon Jul 26 14:39:41 UTC 2021 Mon Jul 26 14:39:43 UTC 2021 Mon Jul 26 14:39:45 UTC 2021 Mon Jul 26 14:39:47 UTC 2021 Mon Jul 26 14:39:49 UTC 2021 Mon Jul 26 14:39:51 UTC 2021

      This is essentially the same as opening up an interactive shell for the Docker container (as done in the previous step with docker exec -it container-name sh) and then running the tail /var/log/date.log command. However, rather than opening up a shell, running the command, and then closing the shell, this command returns that same output in a single command and without opening up a pseudo-terminal.

      Running Commands in an Alternate Directory in a Docker Container

      To run a command in a certain directory of your container, use the --workdir flag to specify the directory:

      • docker exec --workdir /tmp container-name pwd

      This example command sets the /tmp directory as the working directory, then runs the pwd command, which prints out the present working directory:

      Output

      /tmp

      The pwd command has confirmed that the working directory is /tmp.

      Running Commands as a Different User in a Docker Container

      To run a command as a different user inside your container, add the --user flag:

      • docker exec --user guest container-name whoami

      This will use the guest user to run the whoami command in the container. The whoami command prints out the current user’s username:

      Output

      guest

      The whoami command confirms that the container’s current user is guest.

      Passing Environment Variables into a Docker Container

      Sometimes you need to pass environment variables into a container along with the command to run. The -e flag lets you specify an environment variable:

      • docker exec -e TEST=sammy container-name env

      This command sets the TEST environment variable to equal sammy, then runs the env command inside the container. The env command then prints out all the environment variables:

      Output

      PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin HOSTNAME=76aded7112d4 TEST=sammy HOME=/root

      The TEST variable is set to sammy.

      To set multiple variables, repeat the -e flag for each one:

      • docker exec -e TEST=sammy -e ENVIRONMENT=prod container-name env

      If you’d like to pass in a file full of environment variables you can do that with the --env-file flag.

      First, make the file with a text editor. We’ll open a new file with nano here, but you can use any editor you’re comfortable with:

      We’re using .env as the filename, as that’s a popular standard for using these sorts of files to manage information outside of version control.

      Write your KEY=value variables into the file, one per line, like the following:

      .env

      TEST=sammy
      ENVIRONMENT=prod
      

      Save and close the file. To save the file and exit nano, press CTRL+O, then ENTER to save, then CTRL+X to exit.

      Now run the docker exec command, specifying the correct filename after --env-file:

      • docker exec --env-file .env container-name env

      Output

      PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin HOSTNAME=76aded7112d4 TEST=sammy ENVIRONMENT=prod HOME=/root

      The two variables in the file are set.

      You may specify multiple files by using multiple --env-file flags. If the variables in the files overlap each other, whichever file was listed last in the command will override the previous files.

      Common Errors

      When using the docker exec command, you may encounter a few common errors:

      Error: No such container: container-name
      

      The No such container error means the specified container does not exist, and may indicate a misspelled container name. Use docker ps to list out your running containers and double-check the name.

      Error response from daemon: Container 2a94aae70ea5dc92a12e30b13d0613dd6ca5919174d73e62e29cb0f79db6e4ab is not running
      

      This not running message means that the container exists, but it is stopped. You can start the container with docker start container-name

      Error response from daemon: Container container-name is paused, unpause the container before exec
      

      The Container is paused error explains the problem fairly well. You need to unpause the container with docker unpause container-name before proceeding.

      Conclusion

      In this tutorial we learned how to execute commands in a running Docker container, along with some command line options available when doing so.

      For more information on Docker in general, please see our Docker tag page, which has links to Docker tutorials, Docker-related Q&A pages, and more.

      For help with installing Docker, take a look at How To Install and Use Docker on Ubuntu 20.04.



      Source link

      How To Create Artisan Commands To Manage Database Records in Laravel



      Part of the Series:
      How To Build a Links Landing Page in PHP with Laravel and Docker Compose

      Laravel is an open-source PHP framework that provides a set of tools and resources to build modern PHP applications. In this project-based tutorial series, you’ll build a Links Landing Page application with the Laravel framework, using a containerized PHP development environment managed by Docker Compose.

      At the end, you’ll have a one-page website built with Laravel and managed via Artisan commands where you can share relevant links to an audience on social channels and presentations.

      If you followed along with this series so far, your database tables should be all set. However, you still need to implement a way to let users insert new entries in the links table.

      To limit the scope of this series while also making the application fully-functional, you’ll set up Artisan commands to create and delete links in the database. Artisan is the command line tool that comes with Laravel, offering a number of utilities to speed up the development process, from generating boilerplate code to deleting and re-creating the application’s database.

      Using the command line interface to manage your application can be an alternative to web forms and secured areas, since it requires a user to be logged on the server in order to execute such commands instead of being authenticated from a browser. If you decide later on to create a secured area for your application, you can create web forms to allow a registered user to submit a new link to the database.

      Artisan commands are often used to perform application tasks that should run in the background, either manually or automatically via a scheduling mechanism such as Crontab. They can also be used to facilitate prototyping new application features that need to be configured dynamically, depending on input from an authorized user.

      To get started, create a new Artisan command using the make:command helper:

      • docker-compose exec app php artisan make:command LinkNew

      Output

      Console command created successfully.

      This will create a file named LinkNew.php, located at the app/Console/Commands directory. In this class, which extends from the IlluminateConsoleCommand parent class, you’ll need to implement a handle method that will be executed when this command is called. To define the signature of the command, you’ll set the $signature protected property to link:new.

      Open the new file using your text or code editor of choice. Here, we’ll use nano:

      • nano app/Console/Commands/LinkNew.php

      A few different things will need to happen in the handle method so that you are able to save a new link to the database. First, you’ll prompt for the user’s input in order to obtain the link URL.

       $url = $this->ask('Link URL:');
      

      Then, you’ll use the filter_var function to validate that the input obtained from the user is a valid URL. If the link is invalid, you’ll show an error and exit the application with status code 1, which means the application exited in error.

              if (!filter_var($url, FILTER_VALIDATE_URL)) {
                  $this->error("Invalid URL. Exiting...");
                  return 1;
              }
      

      If the link is valid, you’ll continue and ask for the link description using the same method as before.

       $description = $this->ask('Link Description:');
      

      You’ll then ask for a final confirmation that all data is correct, using the confirm helper. If the user confirms, the link is finally inserted in the database. You’ll use the Link Eloquent model created in a previous part of this series to interact with the database.

              $this->info("New Link:");
              $this->info($url . ' - ' . $description);
      
              if ($this->confirm('Is this information correct?')) {
                  $link = new Link();
                  $link->url = $url;
                  $link->description = $description;
                  $link->save();
      
                  $this->info("Saved.");
              }
      

      The application exits with a 0, representing a success status (0 errors).

      return 0;
      

      The following code contains the full implementation of these steps. Replace the current content in your LinkNew class with:

      app/Console/Commands/LinkNew.php

      <?php
      
      namespace AppConsoleCommands;
      
      use AppModelsLink;
      use IlluminateConsoleCommand;
      use IlluminateSupportFacadesDB;
      
      class LinkNew extends Command
      {
          /**
           * The name and signature of the console command.
           *
           * @var string
           */
          protected $signature="link:new";
      
          /**
           * The console command description.
           *
           * @var string
           */
          protected $description = 'Create a New Link';
      
          /**
           * Create a new command instance.
           *
           * @return void
           */
          public function __construct()
          {
              parent::__construct();
          }
      
          /**
           * Execute the console command.
           *
           * @return int
           */
          public function handle()
          {
              $url = $this->ask('Link URL:');
      
              if (!filter_var($url, FILTER_VALIDATE_URL)) {
                  $this->error("Invalid URL. Exiting...");
                  return 1;
              }
      
              $description = $this->ask('Link Description:');
      
              $this->info("New Link:");
              $this->info($url . ' - ' . $description);
      
              if ($this->confirm('Is this information correct?')) {
                  $link = new Link();
                  $link->url = $url;
                  $link->description = $description;
                  $link->save();
      
                  $this->info("Saved.");
              }
      
              return 0;
          }
      }
      

      Save and close the file when you’re done.

      To execute the command and insert a new link in the database, run:

      • docker-compose exec app php artisan link:new

      Output

      Link URL:: > https://digitalocean.com/community Link Description:: > DigitalOcean Community New Link: https://digitalocean.com/community - DigitalOcean Community Is this information correct? (yes/no) [no]: > yes Saved.

      Feel free to add a few more links if you want to.

      Next, you’ll need to create a new Artisan command to show the list of all links.You can call it link:list. Create the new command with:

      • docker-compose exec app php artisan make:command LinkList

      Open the command class using your text or code editor of choice:

      • nano app/Console/Commands/LinkList.php

      Within the handle method of this command, you’ll query for all rows in the links table. You can use the Link model to access the underlying database query methods that Eloquent provides. To exhibit the results nicely in the command line, you can use the table output helper:

              $headers = [ 'id', 'url', 'description' ];
              $links = Link::all(['id', 'url', 'description'])->toArray();
              $this->table($headers, $links);
      
              return 0;
      

      The following code contains the full implementation of the link:list command. Replace the content in your LinkList.php file with :

      app/Console/Commands/LinkList.php

      <?php
      
      namespace AppConsoleCommands;
      
      use AppModelsLink;
      use IlluminateConsoleCommand;
      
      class LinkList extends Command
      {
          /**
           * The name and signature of the console command.
           *
           * @var string
           */
          protected $signature="link:list";
      
          /**
           * The console command description.
           *
           * @var string
           */
          protected $description = 'List links saved in the database';
      
          /**
           * Create a new command instance.
           *
           * @return void
           */
          public function __construct()
          {
              parent::__construct();
          }
      
          /**
           * Execute the console command.
           *
           * @return int
           */
          public function handle()
          {
              $headers = [ 'id', 'url', 'description' ];
              $links = Link::all(['id', 'url', 'description'])->toArray();
              $this->table($headers, $links);
      
              return 0;
          }
      }
      

      Save and close the file when you are done.

      To run this command and show a list of all links already inserted in the linkstable, run:

      • docker-compose exec app php artisan link:list

      Output

      +----+------------------------------------+--------------+ | id | url | description | +----+------------------------------------+--------------+ | 1 | https://digitalocean.com/community | DO Community | | 2 | https://laravel.com | Laravel | +----+------------------------------------+--------------+

      Finally, you’ll create a command to delete links:

      • docker-compose exec app php artisan make:command LinkDelete

      Output

      Console command created successfully.

      Open the new file using your text or code editor of choice:

      • nano app/Console/Commands/LinkDelete.php

      You can name this command link:delete. To know which link must be deleted, you’ll need to require that users provide an additional argument when calling the command: the ID of the link. This is also set within the $signature variable, which defines how your command is called and what arguments, mandatory or not, should be provided:

      protected $signature="link:delete {link_id}";
      

      The handle method for this command will implement a few different instructions. First, you’ll obtain the Link ID that should have been provided within the command call.

      $link_id = $this->argument('link_id');
      

      Then, you’ll obtain the referenced link from the database, using the Eloquent method find that is available through your Link model.

      $link = Link::find($link_id);
      

      When the find method doesn’t find a database record with that ID, it will return null. You’ll check if that is the current value contained in the $link variable, and return an error in that case. The program will exit in error (code 1).

              if ($link === null) {
                  $this->error("Invalid or non-existent link ID.");
                  return 1;
              }
      

      When $link is not null, the command continues execution. You then use the confirm helper to ask for a user confirmation.

      if ($this->confirm('Are you sure you want to delete this link? ' . $link->url)) {
          // deletes link
      }
      

      When the user confirms the action by typing yes and hitting ENTER, you’ll call the delete method from the Link Eloquent model to delete the specified link from the database.

                  $link->delete();
                  $this->info("Link deleted.");
      

      The following code contains the full implementation for the list:delete command. Replace the content in your LinkDelete.php file with the following:

      app/Console/Commands/LinkDelete.php

      <?php
      
      namespace AppConsoleCommands;
      
      use AppModelsLink;
      use IlluminateConsoleCommand;
      use IlluminateSupportFacadesDB;
      
      class LinkDelete extends Command
      {
          /**
           * The name and signature of the console command.
           *
           * @var string
           */
          protected $signature="link:delete {link_id}";
      
          /**
           * The console command description.
           *
           * @var string
           */
          protected $description = 'Deletes a link from the database.';
      
          /**
           * Create a new command instance.
           *
           * @return void
           */
          public function __construct()
          {
              parent::__construct();
          }
      
          /**
           * Execute the console command.
           *
           * @return int
           */
          public function handle()
          {
              $link_id = $this->argument('link_id');
              $link = Link::find($link_id);
      
              if ($link === null) {
                  $this->error("Invalid or non-existent link ID.");
                  return 1;
              }
      
              if ($this->confirm('Are you sure you want to delete this link? ' . $link->url)) {
                  $link->delete();
                  $this->info("Link deleted.");
              }
      
              return 0;
          }
      }
      

      Save and close the file when you’re done.

      Now when you want to delete a link from your links table, you’ll first need to obtain the link’s ID with artisan link:list, as demonstrated earlier on. Once you know the ID of a link, you can run the artisan link:delete command with:

      • docker-compose exec app php artisan link:delete LINK_ID

      Output

      Are you sure you want to delete this link? https://laravel.com (yes/no) [no]: > yes Link deleted.

      You’re now able to insert, list, and delete links in the application’s database, using Artisan commands executed from a command-line interface. In the next part of this series, you’ll set up the front end of your application using Blade templates and the Bulma CSS framework.



      Source link

      How To Manage Multiple Servers with Ansible Ad Hoc Commands


      Introduction

      Ansible is a modern configuration management tool that facilitates the task of setting up and maintaining remote servers. With a minimalist design intended to get users up and running quickly, it allows you to control one to hundreds of systems from a central location with either playbooks or ad hoc commands.

      Unlike playbooks — which consist of collections of tasks that can be reused — ad hoc commands are tasks that you don’t perform frequently, such as restarting a service or retrieving information about the remote systems that Ansible manages.

      In this cheat sheet guide, you’ll learn how to use Ansible ad hoc commands to perform common tasks such as installing packages, copying files, and restarting services on one or more remote servers, from an Ansible control node.

      Prerequisites

      In order to follow this guide, you’ll need:

      • One Ansible control node. This guide assumes your control node is an Ubuntu 20.04 machine with Ansible installed and configured to connect to your Ansible hosts using SSH keys. Make sure the control node has a regular user with sudo permissions and a firewall enabled, as explained in our Initial Server Setup guide. To set up Ansible, please follow our guide on How to Install and Configure Ansible on Ubuntu 20.04.
      • Two or more Ansible hosts. An Ansible host is any machine that your Ansible control node is configured to automate. This guide assumes your Ansible hosts are remote Ubuntu 20.04 servers. Make sure each Ansible host has:
        • The Ansible control node’s SSH public key added to the authorized_keys of a system user. This user can be either root or a regular user with sudo privileges. To set this up, you can follow Step 2 of How to Set Up SSH Keys on Ubuntu 20.04.
      • An inventory file set up on the Ansible control node. Make sure you have a working inventory file containing all your Ansible hosts. To set this up, please refer to the guide on How To Set Up Ansible Inventories. Then, make sure you’re able to connect to your nodes by running the connection test outlined in the section Testing Connection to Ansible Hosts.

      Testing Connection to Ansible Hosts

      The following command will test connectivity between your Ansible control node and all your Ansible hosts. This command uses the current system user and its corresponding SSH key as the remote login, and includes the -m option, which tells Ansible to run the ping module. It also features the -i flag, which tells Ansible to ping the hosts listed in the specified inventory file

      • ansible all -i inventory -m ping

      If this is the first time you’re connecting to these servers via SSH, you’ll be asked to confirm the authenticity of the hosts you’re connecting to via Ansible. When prompted, type yes and then hit ENTER to confirm.

      You should get output similar to this:

      Output

      server1 | SUCCESS => { "changed": false, "ping": "pong" } server2 | SUCCESS => { "changed": false, "ping": "pong" }

      Once you get a "pong" reply back from a host, it means the connection is live and you’re ready to run Ansible commands on that server.

      Adjusting Connection Options

      By default, Ansible tries to connect to the nodes as a remote user with the same name as your current system user, using its corresponding SSH keypair.

      To connect as a different remote user, append the command with the -u flag and the name of the intended user:

      • ansible all -i inventory -m ping -u sammy

      If you’re using a custom SSH key to connect to the remote servers, you can provide it at execution time with the --private-key option:

      • ansible all -i inventory -m ping --private-key=~/.ssh/custom_id

      Note: For more information on how to connect to nodes, please refer to our How to Use Ansible guide, which demonstrates more connection options.

      Once you’re able to connect using the appropriate options, you can adjust your inventory file to automatically set your remote user and private key, in case they are different from the default values assigned by Ansible. Then, you won’t need to provide those parameters in the command line.

      The following example inventory file sets up the ansible_user variable only for the server1 server:

      ~/ansible/inventory

      server1 ansible_host=203.0.113.111 ansible_user=sammy
      server2 ansible_host=203.0.113.112
      

      Ansible will now use sammy as the default remote user when connecting to the server1 server.

      To set up a custom SSH key, include the ansible_ssh_private_key_file variable as follows:

      ~/ansible/inventory

      server1 ansible_host=203.0.113.111 ansible_ssh_private_key_file=/home/sammy/.ssh/custom_id
      server2 ansible_host=203.0.113.112
      

      In both cases, we have set up custom values only for server1. If you want to use the same settings for multiple servers, you can use a child group for that:

      ~/ansible/inventory

      [group_a]
      203.0.113.111
      203.0.113.112
      
      [group_b]
      203.0.113.113
      
      
      [group_a:vars]
      ansible_user=sammy
      ansible_ssh_private_key_file=/home/sammy/.ssh/custom_id
      

      This example configuration will assign a custom user and SSH key only for connecting to the servers listed in group_a.

      Defining Targets for Command Execution

      When running ad hoc commands with Ansible, you can target individual hosts, as well as any combination of groups, hosts and subgroups. For instance, this is how you would check connectivity for every host in a group named servers:

      • ansible servers -i inventory -m ping

      You can also specify multiple hosts and groups by separating them with colons:

      • ansible server1:server2:dbservers -i inventory -m ping

      To include an exception in a pattern, use an exclamation mark, prefixed by the escape character , as follows. This command will run on all servers from group1, except server2:

      • ansible group1:!server2 -i inventory -m ping

      In case you’d like to run a command only on servers that are part of both group1 and group2, for instance, you should use & instead. Don’t forget to prefix it with a escape character:

      • ansible group1:&group2 -i inventory -m ping

      For more information on how to use patterns when defining targets for command execution, please refer to Step 5 of our guide on How to Set Up Ansible Inventories.

      Running Ansible Modules

      Ansible modules are pieces of code that can be invoked from playbooks and also from the command-line to facilitate executing procedures on remote nodes. Examples include the apt module, used to manage system packages on Ubuntu, and the user module, used to manage system users. The ping command used throughout this guide is also a module, typically used to test connection from the control node to the hosts.

      Ansible ships with an extensive collection of built-in modules, some of which require the installation of additional software in order to provide full functionality. You can also create your own custom modules using your language of choice.

      To execute a module with arguments, include the -a flag followed by the appropriate options in double quotes, like this:

      ansible target -i inventory -m module -a "module options"
      

      As an example, this will use the apt module to install the package tree on server1:

      • ansible server1 -i inventory -m apt -a "name=tree"

      Running Bash Commands

      When a module is not provided via the -m option, the command module is used by default to execute the specified command on the remote server(s).

      This allows you to execute virtually any command that you could normally execute via an SSH terminal, as long as the connecting user has sufficient permissions and there aren’t any interactive prompts.

      This example executes the uptime command on all servers from the specified inventory:

      • ansible all -i inventory -a "uptime"

      Output

      server1 | CHANGED | rc=0 >> 14:12:18 up 55 days, 2:15, 1 user, load average: 0.03, 0.01, 0.00 server2 | CHANGED | rc=0 >> 14:12:19 up 10 days, 6:38, 1 user, load average: 0.01, 0.02, 0.00

      Using Privilege Escalation to Run Commands with sudo

      If the command or module you want to execute on remote hosts requires extended system privileges or a different system user, you’ll need to use Ansible’s privilege escalation module, become. This module is an abstraction for sudo as well as other privilege escalation software supported by Ansible on different operating systems.

      For instance, if you wanted to run a tail command to output the latest log messages from Nginx’s error log on a server named server1 from inventory, you would need to include the --become option as follows:

      • ansible server1 -i inventory -a "tail /var/log/nginx/error.log" --become

      This would be the equivalent of running a sudo tail /var/log/nginx/error.log command on the remote host, using the current local system user or the remote user set up within your inventory file.

      Privilege escalation systems such as sudo often require that you confirm your credentials by prompting you to provide your user’s password. That would cause Ansible to fail a command or playbook execution. You can then use the --ask-become-pass or -K option to make Ansible prompt you for that sudo password:

      • ansible server1 -i inventory -a "tail /var/log/nginx/error.log" --become -K

      Installing and Removing Packages

      The following example uses the apt module to install the nginx package on all nodes from the provided inventory file:

      • ansible all -i inventory -m apt -a "name=nginx" --become -K

      To remove a package, include the state argument and set it to absent:.

      • ansible all -i inventory -m apt -a "name=nginx state=absent" --become -K

      Copying Files

      With the file module, you can copy files between the control node and the managed nodes, in either direction. The following command copies a local text file to all remote hosts in the specified inventory file:

      • ansible all -i inventory -m copy -a "src=./file.txt dest=~/myfile.txt"

      To copy a file from the remote server to your control node, include the remote_src option:

      • ansible all -i inventory -m copy -a "src=~/myfile.txt remote_src=yes dest=./file.txt"

      Changing File Permissions

      To modify permissions on files and directories on your remote nodes, you can use the file module.

      The following command will adjust permissions on a file named file.txt located at /var/www on the remote host. It will set the file’s umask to 600, which will enable read and write permissions only for the current file owner. Additionally, it will set the ownership of that file to a user and a group called sammy:

      • ansible all -i inventory -m file -a "dest=/var/www/file.txt mode=600 owner=sammy group=sammy" --become -K

      Because the file is located in a directory typically owned by root, we might need sudo permissions to modify its properties. That’s why we include the --become and -K options. These will use Ansible’s privilege escalation system to run the command with extended privileges, and it will prompt you to provide the sudo password for the remote user.

      Restarting Services

      You can use the service module to manage services running on the remote nodes managed by Ansible. This will require extended system privileges, so make sure your remote user has sudo permissions and you include the --become option to use Ansible’s privilege escalation system. Using -K will prompt you to provide the sudo password for the connecting user.

      To restart the nginx service on all hosts in group called webservers, for instance, you would run:

      • ansible webservers -i inventory -m service -a "name=nginx state=restarted" --become -K

      Restarting Servers

      Although Ansible doesn’t have a dedicated module to restart servers, you can issue a bash command that calls the /sbin/reboot command on the remote host.

      Restarting the server will require extended system privileges, so make sure your remote user has sudo permissions and you include the --become option to use Ansible’s privilege escalation system. Using -K will prompt you to provide the sudo password for the connecting user.

      Warning: The following command will fully restart the server(s) targeted by Ansible. That might cause temporary disruption to any applications that rely on those servers.

      To restart all servers in a webservers group, for instance, you would run:

      • ansible webservers -i inventory -a "/sbin/reboot" --become -K

      Gathering Information About Remote Nodes

      The setup module returns detailed information about the remote systems managed by Ansible, also known as system facts.

      To obtain the system facts for server1, run:

      • ansible server1 -i inventory -m setup

      This will print a large amount of JSON data containing details about the remote server environment. To print only the most relevant information, include the "gather_subset=min" argument as follows:

      • ansible server1 -i inventory -m setup -a "gather_subset=min"

      To print only specific items of the JSON, you can use the filter argument. This will accept a wildcard pattern used to match strings, similar to fnmatch. For example, to obtain information about both the ipv4 and ipv6 network interfaces, you can use *ipv* as filter:

      • ansible server1 -i inventory -m setup -a "filter=*ipv*"

      Output

      server1 | SUCCESS => { "ansible_facts": { "ansible_all_ipv4_addresses": [ "203.0.113.111", "10.0.0.1" ], "ansible_all_ipv6_addresses": [ "fe80::a4f5:16ff:fe75:e758" ], "ansible_default_ipv4": { "address": "203.0.113.111", "alias": "eth0", "broadcast": "203.0.113.111", "gateway": "203.0.113.1", "interface": "eth0", "macaddress": "a6:f5:16:75:e7:58", "mtu": 1500, "netmask": "255.255.240.0", "network": "203.0.113.0", "type": "ether" }, "ansible_default_ipv6": {} }, "changed": false }

      If you’d like to check disk usage, you can run a Bash command calling the df utility, as follows:

      • ansible all -i inventory -a "df -h"

      Output

      server1 | CHANGED | rc=0 >> Filesystem Size Used Avail Use% Mounted on udev 3.9G 0 3.9G 0% /dev tmpfs 798M 624K 798M 1% /run /dev/vda1 155G 2.3G 153G 2% / tmpfs 3.9G 0 3.9G 0% /dev/shm tmpfs 5.0M 0 5.0M 0% /run/lock tmpfs 3.9G 0 3.9G 0% /sys/fs/cgroup /dev/vda15 105M 3.6M 101M 4% /boot/efi tmpfs 798M 0 798M 0% /run/user/0 server2 | CHANGED | rc=0 >> Filesystem Size Used Avail Use% Mounted on udev 2.0G 0 2.0G 0% /dev tmpfs 395M 608K 394M 1% /run /dev/vda1 78G 2.2G 76G 3% / tmpfs 2.0G 0 2.0G 0% /dev/shm tmpfs 5.0M 0 5.0M 0% /run/lock tmpfs 2.0G 0 2.0G 0% /sys/fs/cgroup /dev/vda15 105M 3.6M 101M 4% /boot/efi tmpfs 395M 0 395M 0% /run/user/0

      Conclusion

      In this guide, we demonstrated how to use Ansible ad hoc commands to manage remote servers, including how to execute common tasks such as restarting a service or copying a file from the control node to the remote servers managed by Ansible. We’ve also seen how to gather information from the remote nodes using limiting and filtering parameters.

      As an additional resource, you can check Ansible’s official documentation on ad hoc commands.



      Source link