create a directory test at /home/user using ansible-adhoc command - ansible

I am trying to create directory using below command
ansible app -m file -a "path=/home/user/test mode = 777 state = directory" -b
I am getting below error message. Could any one advise me what I am doing wrong here?
ERROR! this task 'file' has extra params, which is only allowed in the
following modules: ansible.builtin.raw, ansible.legacy.add_host,
ansible.builtin.meta, ansible.legacy.include,
ansible.legacy.import_role, script, ansible.legacy.raw, group_by,
ansible.builtin.shell, ansible.legacy.win_command, include, shell,
include_vars, ansible.builtin.import_tasks, add_host,
ansible.builtin.include_vars, ansible.legacy.include_role,
ansible.builtin.include_role, ansible.legacy.include_vars,
ansible.legacy.win_shell, ansible.legacy.group_by, import_tasks,
ansible.builtin.set_fact, ansible.builtin.command,
ansible.builtin.include_tasks, include_tasks, ansible.builtin.script,
ansible.builtin.include, raw, meta, ansible.legacy.set_fact,
ansible.builtin.add_host, ansible.legacy.script,
ansible.legacy.import_tasks, win_command, ansible.builtin.win_shell,
include_role, win_shell, set_fact, ansible.legacy.shell,
ansible.legacy.command, import_role, ansible.legacy.meta,
ansible.builtin.import_role, ansible.legacy.include_tasks,
ansible.builtin.group_by, ansible.builtin.win_command, command

The simplest example of an ad hoc command to create a directory using Ansible is
ansible nodes -a "mkdir /BYANSIBLE"

Try this:
ansible app -m file -a "dest=/home/user/test state=directory"
or
ansible localhost -m file -a "dest=/home/user/test state=directory"

In general, for an Ansible ad-hoc command, any module arguments are supplied using the -a option, as one single string. Due to this, the way Ansible distinguishes the individual arguments, is by spaces.
You need to remove the extra spaces you have on either side of the equal signs for the ad-hoc command to work.
Hence, the following would work:
ansible app -m file -a "path=/home/user/test mode=755 state=directory" -b
Also, check out some of the related examples in the Ansible docs.
Side note: I've modified the permissions to 755 (read/write/execute for owner + read/execute for group & others). Its almost never a good idea to give 777 permissions (full read/write/execute) on directories.

Related

Could i use ansible playbook(tgz,zip format ) like helm charts?

I want to use ansible to manage multi service deployment, each service have many roles. Now I want to package one service as a tgz or zip file(same as helm charts), and use one file to override variables when use ansible execute(like helm install xx.tgz --values values.yml)
I am new to ansible, and have checked ansible-playbook -h, but no find some related information
Usage: ansible-playbook [options] playbook.yml [playbook2 ...]
Runs Ansible playbooks, executing the defined tasks on the targeted hosts.
Options:
--ask-vault-pass ask for vault password
-C, --check don't make any changes; instead, try to predict some
of the changes that may occur
-D, --diff when changing (small) files and templates, show the
differences in those files; works great with --check
-e EXTRA_VARS, --extra-vars=EXTRA_VARS
set additional variables as key=value or YAML/JSON, if
filename prepend with #
--flush-cache clear the fact cache for every host in inventory
--force-handlers run handlers even if a task fails
-f FORKS, --forks=FORKS
specify number of parallel processes to use
(default=5)
-h, --help show this help message and exit
-i INVENTORY, --inventory=INVENTORY, --inventory-file=INVENTORY
specify inventory host path or comma separated host
list. --inventory-file is deprecated
-l SUBSET, --limit=SUBSET
further limit selected hosts to an additional pattern
--list-hosts outputs a list of matching hosts; does not execute
anything else
--list-tags list all available tags
--list-tasks list all tasks that would be executed
-M MODULE_PATH, --module-path=MODULE_PATH
prepend colon-separated path(s) to module library (def
ault=~/.ansible/plugins/modules:/usr/share/ansible/plu
gins/modules)
--skip-tags=SKIP_TAGS
only run plays and tasks whose tags do not match these
values
--start-at-task=START_AT_TASK
start the playbook at the task matching this name
--step one-step-at-a-time: confirm each task before running
--syntax-check perform a syntax check on the playbook, but do not
execute it
-t TAGS, --tags=TAGS only run plays and tasks tagged with these values
--vault-id=VAULT_IDS the vault identity to use
--vault-password-file=VAULT_PASSWORD_FILES
vault password file
-v, --verbose verbose mode (-vvv for more, -vvvv to enable
connection debugging)
--version show program's version number, config file location,
configured module search path, module location,
executable location and exit
Connection Options:
control as whom and how to connect to hosts
-k, --ask-pass ask for connection password
--private-key=PRIVATE_KEY_FILE, --key-file=PRIVATE_KEY_FILE
use this file to authenticate the connection
-u REMOTE_USER, --user=REMOTE_USER
connect as this user (default=None)
-c CONNECTION, --connection=CONNECTION
connection type to use (default=smart)
-T TIMEOUT, --timeout=TIMEOUT
override the connection timeout in seconds
(default=10)
--ssh-common-args=SSH_COMMON_ARGS
specify common arguments to pass to sftp/scp/ssh (e.g.
ProxyCommand)
--sftp-extra-args=SFTP_EXTRA_ARGS
specify extra arguments to pass to sftp only (e.g. -f,
-l)
--scp-extra-args=SCP_EXTRA_ARGS
specify extra arguments to pass to scp only (e.g. -l)
--ssh-extra-args=SSH_EXTRA_ARGS
specify extra arguments to pass to ssh only (e.g. -R)
Privilege Escalation Options:
control how and which user you become as on target hosts
-b, --become run operations with become (does not imply password
prompting)
--become-method=BECOME_METHOD
privilege escalation method to use (default=sudo), use
`ansible-doc -t become -l` to list valid choices.
--become-user=BECOME_USER
run operations as this user (default=root)
-K, --ask-become-pass
ask for privilege escalation password
version:ansible 2.8.0
You can't package playbooks as zip or tgz files. One option would be to use ansible-pull. It checks a repository out and runs a specified playbook: https://docs.ansible.com/ansible/latest/cli/ansible-pull.html

Problem with Ansible EC2 dynamic inventory

I am trying to use ansible dynamic inventory.
I am getting the results when I run,
$ ./ec2.py --list
...
...
"ec2": [
"xx.xx.xx.xx"
]
}
But when I try to run it with ansible command, it does not run successfully.
$ ansible -i ec2.py -e "ansible_ssh_port=3003" -m ping
Usage: ansible <host-pattern> [options]
Define and run a single task 'playbook' against a set of hosts
Options:
-a MODULE_ARGS, --args=MODULE_ARGS
module arguments
--ask-vault-pass ask for vault password
-B SECONDS, --background=SECONDS
run asynchronously, failing after X seconds
(default=N/A)
-C, --check don't make any changes; instead, try to predict some
of the changes that may occur
-D, --diff when changing (small) files and templates, show the
differences in those files; works great with --check
-e EXTRA_VARS, --extra-vars=EXTRA_VARS
set additional variables as key=value or YAML/JSON, if
filename prepend with #
-f FORKS, --forks=FORKS
specify number of parallel processes to use
(default=5)
-h, --help show this help message and exit
-i INVENTORY, --inventory=INVENTORY, --inventory-file=INVENTORY
specify inventory host path or comma separated host
list. --inventory-file is deprecated
-l SUBSET, --limit=SUBSET
further limit selected hosts to an additional pattern
--list-hosts outputs a list of matching hosts; does not execute
anything else
-m MODULE_NAME, --module-name=MODULE_NAME
module name to execute (default=command)
-M MODULE_PATH, --module-path=MODULE_PATH
prepend colon-separated path(s) to module library (def
ault=['/Users/luvpreetsingh/.ansible/plugins/modules',
'/usr/share/ansible/plugins/modules'])
-o, --one-line condense output
--playbook-dir=BASEDIR
Since this tool does not use playbooks, use this as a
subsitute playbook directory.This sets the relative
path for many features including roles/ group_vars/
etc.
-P POLL_INTERVAL, --poll=POLL_INTERVAL
set the poll interval if using -B (default=15)
--syntax-check perform a syntax check on the playbook, but do not
execute it
-t TREE, --tree=TREE log output to this directory
--vault-id=VAULT_IDS the vault identity to use
--vault-password-file=VAULT_PASSWORD_FILES
vault password file
-v, --verbose verbose mode (-vvv for more, -vvvv to enable
connection debugging)
--version show program's version number and exit
Connection Options:
control as whom and how to connect to hosts
-k, --ask-pass ask for connection password
--private-key=PRIVATE_KEY_FILE, --key-file=PRIVATE_KEY_FILE
use this file to authenticate the connection
-u REMOTE_USER, --user=REMOTE_USER
connect as this user (default=None)
-c CONNECTION, --connection=CONNECTION
connection type to use (default=smart)
-T TIMEOUT, --timeout=TIMEOUT
override the connection timeout in seconds
(default=10)
--ssh-common-args=SSH_COMMON_ARGS
specify common arguments to pass to sftp/scp/ssh (e.g.
ProxyCommand)
--sftp-extra-args=SFTP_EXTRA_ARGS
specify extra arguments to pass to sftp only (e.g. -f,
-l)
--scp-extra-args=SCP_EXTRA_ARGS
specify extra arguments to pass to scp only (e.g. -l)
--ssh-extra-args=SSH_EXTRA_ARGS
specify extra arguments to pass to ssh only (e.g. -R)
Privilege Escalation Options:
control how and which user you become as on target hosts
-s, --sudo run operations with sudo (nopasswd) (deprecated, use
become)
-U SUDO_USER, --sudo-user=SUDO_USER
desired sudo user (default=root) (deprecated, use
become)
-S, --su run operations with su (deprecated, use become)
-R SU_USER, --su-user=SU_USER
run operations with su as this user (default=None)
(deprecated, use become)
-b, --become run operations with become (does not imply password
prompting)
--become-method=BECOME_METHOD
privilege escalation method to use (default=sudo),
valid choices: [ sudo | su | pbrun | pfexec | doas |
dzdo | ksu | runas | pmrun | enable ]
--become-user=BECOME_USER
run operations as this user (default=root)
--ask-sudo-pass ask for sudo password (deprecated, use become)
--ask-su-pass ask for su password (deprecated, use become)
-K, --ask-become-pass
ask for privilege escalation password
Some modules do not make sense in Ad-Hoc (include, meta, etc)
ERROR! Missing target hosts
I get this long statement with the error of missing target hosts.
Then, when I run by specifying the region, it does not give any error but does not return any instances.
$ ansible -i ec2.py us-west-2 -e "ansible_ssh_port=3003" -m ping
[WARNING]: Could not match supplied host pattern, ignoring: us-west-2
[WARNING]: No hosts matched, nothing to do
Firstly, why is it not running? what am I doing wrong?
Secondly, why do the error changes when I specify the region? Is specifying region mandatory? shouldn't it pick the region from ec2.ini?
You do not have any hosts listed. Try adding all at the end of your ansible command:
ansible -i ec2.py -e "ansible_ssh_port=3003" -m ping all
The above command is partly right. The inventory has been specified with the -i argument but the target host group has not been specified. The command should be
ansible all -i ec2.py -e "ansible_ssh_port=3003" -m ping
# The command syntax could be written as below
ansible <target_host_group> -i <inventory> -e "extra_vars" -m "module_name" -a "module_arguments"
Please refer to the documentation on Working with patterns and Ad-Hoc Commands from the ansible documentation.

Pass multiple commands in ad-hoc mode in Cisco ios_command module

I would like to know how can I pass multiple show commands in ios_command module in ad-hoc mode.
Sample with just one command:
ansible all -m ios_command -a "commands='show version'"
Now here I would like to send another command, say show run or any other.
Any suggestions on this would be appreciated.
You need to pass a list and you can do it using JSON string:
ansible all -m ios_command -a "commands='[ \"show version\", \"show run\" ]'"
If you leave the spaces out, you can squeeze to 'commands=["show version","show run"]'
I use the following:
ansible ios-device -m ios_command -a commands="{{ lookup('file', 'commands.txt') }}" -u username -k
where commands.txt contains
show version
You can add more commands on each line of the 'commands.txt' file.

Writing a string to file using Ad-Hoc Commands in Ansible

I'm a beginner with Ansible and trying to write a string to a file with an Ad-Hoc command I'm trying to play around with the replace module. The file I'm trying to write to is /etc/motd/.
ansible replace --sudo /etc/motd "This server is managed by Ansible"
Any help would be appreciated thanks!
Have a look at the lineinfile module usage and a general syntax for Ad hoc commands.
What you are looking for is:
ansible target_node -b -m lineinfile -a 'dest=/etc/motd line="This server is managed by Ansible"'
in extended form:
ansible target_node --become --module-name=lineinfile --args='dest=/etc/motd line="This server is managed by Ansible"'
Explanation:
target_node is the hostname or group name as defined in the Ansible inventory file
--become (-b) instructs Ansible to use sudo
-module-name (-m) specifies the module to run (lineinfile here)
--args (-a) passes arguments to the module (these change depending on a module)
dest points to the destination file
line instructs Ansible to ensure a particular line is in the file
If you would like to replace the whole contents of the /etc/motd you should use copy module.
ansible target_node -b -m copy -a 'dest=/etc/motd content="This server is managed by Ansible"'
Notice one of the arguments is changed accordingly.

How can I ssh directly to a particular directory?

I often have to login to one of several servers and go to one of several directories on those machines. Currently I do something of this sort:
localhost ~]$ ssh somehost
Welcome to somehost!
somehost ~]$ cd /some/directory/somewhere/named/Foo
somehost Foo]$
I have scripts that can determine which host and which directory I need to get into but I cannot figure out a way to do this:
localhost ~]$ go_to_dir Foo
Welcome to somehost!
somehost Foo]$
Is there an easy, clever or any way to do this?
You can do the following:
ssh -t xxx.xxx.xxx.xxx "cd /directory_wanted ; bash --login"
This way, you will get a login shell right on the directory_wanted.
Explanation
-t Force pseudo-terminal allocation. This can be used to execute arbitrary screen-based programs on a remote machine, which can be very useful, e.g. when implementing menu services.
Multiple -t options force tty allocation, even if ssh has no local tty.
If you don't use -t then no prompt will appear.
If you don't add ; bash then the connection will get closed and return control to your local machine
If you don't add bash --login then it will not use your configs because its not a login shell
You could add
cd /some/directory/somewhere/named/Foo
to your .bashrc file (or .profile or whatever you call it) at the other host. That way, no matter what you do or where you ssh from, whenever you log onto that server, it will cd to the proper directory for you, and all you have to do is use ssh like normal.
Of curse, rogeriopvl's solution works too, but it's a tad bit more verbose, and you have to remember to do it every time (unless you make an alias) so it seems a bit less "fun".
My preferred approach is using the SSH config file (described below), but there are a few possible solutions depending on your usages.
Command Line Arguments
I think the best answer for this approach is christianbundy's reply to the accepted answer:
ssh -t example.com "cd /foo/bar; exec \$SHELL -l"
Using double quotes will allow you to use variables from your local machine, unless they are escaped (as $SHELL is here). Alternatively, you can use single quotes, and all of the variables you use will be the ones from the target machine:
ssh -t example.com 'cd /foo/bar; exec $SHELL -l'
Bash Function
You can simplify the command by wrapping it in a bash function. Let's say you just want to type this:
sshcd example.com /foo/bar
You can make this work by adding this to your ~/.bashrc:
sshcd () { ssh -t "$1" "cd \"$2\"; exec \$SHELL -l"; }
If you are using a variable that exists on the remote machine for the directory, be sure to escape it or put it in single quotes. For example, this will cd to the directory that is stored in the JBOSS_HOME variable on the remote machine:
sshcd example.com \$JBOSS_HOME
SSH Config File
If you'd like to see this behavior all the time for specific (or any) hosts with the normal ssh command without having to use extra command line arguments, you can set the RequestTTY and RemoteCommand options in your ssh config file.
For example, I'd like to type only this command:
ssh qaapps18
but want it to always behave like this command:
ssh -t qaapps18 'cd $JBOSS_HOME; exec $SHELL'
So I added this to my ~/.ssh/config file:
Host *apps*
RequestTTY yes
RemoteCommand cd $JBOSS_HOME; exec $SHELL
Now this rule applies to any host with "apps" in its hostname.
For more information, see http://man7.org/linux/man-pages/man5/ssh_config.5.html
I've created a tool to SSH and CD into a server consecutively – aptly named sshcd. For the example you've given, you'd simply use:
sshcd somehost:/some/directory/somewhere/named/Foo
Let me know if you have any questions or problems!
Based on additions to #rogeriopvl's answer, I suggest the following:
ssh -t xxx.xxx.xxx.xxx "cd /directory_wanted && bash"
Chaining commands by && will make the next command run only when the previous one was successful (as opposed to using ;, which executes commands sequentially). This is particularly useful when needing to cd to a directory performing the command.
Imagine doing the following:
/home/me$ cd /usr/share/teminal; rm -R *
The directory teminal doesn't exist, which causes you to stay in the home directory and remove all the files in there with the following command.
If you use &&:
/home/me$ cd /usr/share/teminal && rm -R *
The command will fail after not finding the directory.
In my very specific case, I just wanted to execute a command in a remote host, inside a specific directory from a Jenkins slave machine:
ssh myuser#mydomain
cd /home/myuser/somedir
./commandThatMustBeRunInside_somedir
exit
But my machine couldn't perform the ssh (it couldn't allocate a pseudo-tty I suppose) and kept me giving the following error:
Pseudo-terminal will not be allocated because stdin is not a terminal
I could get around this issue passing "cd to dir + my command" as a parameter of the ssh command (to not have to allocate a Pseudo-terminal) and by passing the option -T to explicitly tell to the ssh command that I didn't need pseudo-terminal allocation.
ssh -T myuser#mydomain "cd /home/myuser/somedir; ./commandThatMustBeRunInside_somedir"
I use the environment variable CDPATH
going one step further with the -t idea. I keep a set of scripts calling the one below to go to specific places in my frequently visited hosts. I keep them all in ~/bin and keep that directory in my path.
#!/bin/bash
# does ssh session switching to particular directory
# $1, hostname from config file
# $2, directory to move to after login
# can save this as say 'con' then
# make another script calling this one, e.g.
# con myhost repos/i2c
ssh -t $1 "cd $2; exec \$SHELL --login"
My answer may differ from what you really want, but I write here as may be useful for some people. In my solution you have to enter into the directory once and then every new ssh session goes to the same dir (after the first logout).
How to ssh to the same directory you have been in your last login.
(I assume you use bash on the remote node.)
Add this line to your ~/.bash_logout on the remote node(!):
echo $PWD > ~/.bash_lastpwd
and these lines to the ~/.bashrc file (still on the remote node!)
if [ -f ~/.bash_lastpwd ]; then
cd $(cat ~/.bash_lastpwd)
fi
This way you save your current path on every logout and .bashrc put you into that directory after login.
ps: You can tweak it further like using the SSH_CLIENT variable to decide to go into that directory or not, so you can differentiate between local logins and ssh or even between different ssh clients.
Another way of going to directly after logging in is create "Alias". When you login into your system just type that alias and you will be in that directory.
Example : Alias = myfolder '/var/www/Folder'
After you log in to your system type that alias (this works from any part of the system)
this command if not in bashrc will work for current session. So you can also add this alias to bashrc to use that in future
$ myfolder => takes you to that folder
I know this has been answered ages ago but I found the question while trying to incorporate an ssh login in a bash script and once logged in run a few commands and log back out and continue with the bash script. The simplest way I found which hasnt been mentioned elsewhere because it is so trivial is to do this.
#!/bin/bash
sshpass -p "password" ssh user#server 'cd /path/to/dir;somecommand;someothercommand;exit;'
Connect With User
In case if you don't know this, you can use this to connect by specifying both user and host
ssh -t <user>#<Host domain / IP> "cd /path/to/directory; bash --login"
Example: ssh -t admin#test.com "cd public_html; bash --login"
You can also append the commands to be executed on every login by appending it in the double quotes with a ; before each command
Unfortunately, the suggested solution (of #rogeriopvl) doesn't work when you use multiple hops, so I found another one.
On remote machine add into ~/.bashrc the following:
[ "x$CDTO" != "x" ] && cd $CDTO
This allows you to specify the desired target directory on command line in this way:
ssh -t host1 ssh -t host2 "CDTO=/desired_directory exec bash --login"
Sure, this way can be used for a single hop too.
This solution can be combined with the usefull tip of #redseven for greater flexibilty (if no $CDTO, go to saved directory, if exists).
SSH itself provides a means of communication, it does not know anything about directories. Since you can specify which remote command to execute (this is - by default - your shell), I'd start there.
simply modify your home with the command:
usermod -d /newhome username

Resources