Utilizing timestamps within filenames

1,556 views
Skip to first unread message

Joe Louthan

unread,
Apr 21, 2016, 5:32:59 PM4/21/16
to Ansible Project
Hello,

In my deployments, I tend to do db backups and dump them into filenames containing a timestamp like so:

mysqldump dbname | gzip -9c > ~/dbname.`date +%Y-%m-%d.%H%M`.sql.gz ; ls -la ~/ | grep `date +%Y-%m-%d`

As you can see, when the dump is done, I want to see the resulting file just to eyeball it and make everything looks right.

(To answer future questions: we date time stamp our backup files so that we can keep them for an extended period of time.)

I would like to write something like this:

- hosts: dbserver
  remote_user: jlouthan
  tasks:
      - name: Backup Prod Database
        shell: mysqldump dbdump | gzip -9c > ~jlouthan/dbdump.`date +%Y-%m-%d`.sql.gz
        become: yes
        become_method: sudo

      - name: Check to see if the dbdump has been successfully created
        wait_for: path=~jlouthan/dbdump.`date +%Y-%m-%d`.sql.gz


Is there any chance that Ansible would be able to pick up on backticks or is there a better way?

Felix Fontein

unread,
Apr 21, 2016, 7:46:45 PM4/21/16
to ansible...@googlegroups.com
Hi Joe,

you could add a task

- name: Get current timestamp
local_action: command bash -c "date +%Y-%m-%d.%H%M"
register: now
run_once: true

(or something similar adapted to your local environment) before your
dump task and then use {{ now }} in the next tasks to always get the
same timestamp.

Best,
Felix

Brian Coca

unread,
Apr 21, 2016, 10:21:26 PM4/21/16
to ansible...@googlegroups.com
You can use a lookup or create a var based on it:

​datestring: ​"{{lookup('pipe', "date +%Y-%m-%d.%H%M")}}"


----------
Brian Coca

Johannes Kastl

unread,
Apr 22, 2016, 2:44:13 PM4/22/16
to ansible...@googlegroups.com
On 21.04.16 17:45 Joe Louthan wrote:
> Is there any chance that Ansible would be able to pick up on backticks or
> is there a better way?

Apart form the other answers, I avoid using backticks and use the
$(date ...) syntax instead (a leading dollar sign and brackets instead
of backticks). Have you tried this?

Johannes



signature.asc

Brian Coca

unread,
Apr 22, 2016, 2:58:30 PM4/22/16
to ansible...@googlegroups.com
$() depends on shell, I prefer it as it is stackable and cleaner than the backticks, but not always available.


----------
Brian Coca

Joe Louthan

unread,
Apr 22, 2016, 4:11:50 PM4/22/16
to Ansible Project, fe...@fontein.de
I ran this:
- hosts: dbserver
  remote_user: jlouthan
  tasks:
      - name: Get current timestamp
        local_action: command bash -c "date +%Y-%m-%d.%H%M"
        register: timestamp
        run_once: true

      - debug: var=timestamp.stdout

      - name: Get current datestamp
        local_action: command bash -c "date +%Y-%m-%d"
        register: datestamp
        run_once: true

      - debug: var=datestamp.stdout

      - name: Backup Stag Database
        mysql_db: state=dump name=dbname target=~jlouthan/dbname.{{ datestamp }}.sql
become: yes
        become_method: sudo
- name: See the the Stag DB backup
shell: ls -la ~jlouthan/ | grep {{ timestamp }}
register: dumpstag
      - debug: var=dumpstag.stdout_lines

      - name: Make sure that the Stag DB Backups look good before you continue
        pause:

And got this:
[jlouthan@ansible-server Playbooks]$ ansible-playbook test-backup-Client-staging-db.yml
SUDO password:

PLAY [dbserver] **************************************************************



GATHERING FACTS ***************************************************************


ok: [dbserver]



TASK: [Get current timestamp] *************************************************
changed: [dbserver -> 127.0.0.1]

TASK: [debug var=timestamp.stdout] ********************************************
ok: [dbserver] => {
    "var": {
        "timestamp.stdout": "2016-04-22.1507"
    }
}

TASK: [Get current datestamp] *************************************************
changed: [dbserver -> 127.0.0.1]

TASK: [debug var=datestamp.stdout] ********************************************
ok: [dbserver] => {
    "var": {
        "datestamp.stdout": "2016-04-22"
    }
}

TASK: [Backup Stag Database] **************************************************
failed: [dbserver] => {"failed": true}
msg: this module requires key=value arguments (['state=dump', 'name=dbname', 'target=~jlouthan/dbname.{changed:', 'True,', 'end:', '2016-04-22 15:07:30.816204,', 'stdout:', '2016-04-22,', 'cmd:', '[bash,', '-c,', 'date +%Y-%m-%d],', 'rc:', '0,', 'start:', '2016-04-22 15:07:30.810278,', 'stderr:', ',', 'delta:', '0:00:00.005926,', 'invocation:', '{module_name:', 'ucommand,', 'module_complex_args:', '{},', 'module_args:', 'ubash -c "date +%Y-%m-%d"},', 'stdout_lines:', '[2016-04-22],', 'warnings:', '[]}.sql'])

FATAL: all hosts have already failed -- aborting

PLAY RECAP ********************************************************************
           to retry, use: --limit @/home/jlouthan/test-backup-Client-staging-db.retry

dbserver                  : ok=5    changed=2    unreachable=0    failed=1

What am I doing wrong?

Brian Coca

unread,
Apr 22, 2016, 4:20:45 PM4/22/16
to ansible...@googlegroups.com, fe...@fontein.de
that the module name in the error is 'ucommand' and the spacing you posted, lends me to believe you are not matching the error to the actual play.


----------
Brian Coca

Felix Fontein

unread,
Apr 22, 2016, 5:00:53 PM4/22/16
to ansible...@googlegroups.com
Hi Joe,

> I ran this:
> - hosts: dbserver
> remote_user: jlouthan
> tasks:
> - name: Get current timestamp
> local_action: command bash -c "date +%Y-%m-%d.%H%M"
> register: timestamp
> run_once: true
>
> - debug: var=timestamp.stdout

as you correctly note here, the variable you need is not timestamp, but
timestamp.stdout.

(I forgot the .stdout in my original mail.)

> - name: Backup Stag Database
> mysql_db: state=dump name=dbname target=~jlouthan/dbname.{{
> datestamp }}.sql

Here you have to write {{ datestamp.stdout }} instead of
{{ datestamp }}; otherwise, instead of just the datestamp, the whole
dict will be appended, which results in the error message you get below.

> TASK: [Backup Stag Database]
> **************************************************
> failed: [dbserver] => {"failed": true}
> msg: this module requires key=value arguments (['state=dump',
> 'name=dbname', 'target=~jlouthan/dbname.{changed:', 'True,', 'end:',
> '2016-04-22 15:07:30.816204,', 'stdout:', '2016-04-22,', 'cmd:',
> '[bash,', '-c,', 'date +%Y-%m-%d],', 'rc:', '0,', 'start:',
> '2016-04-22 15:07:30.810278,', 'stderr:', ',', 'delta:',
> '0:00:00.005926,', 'invocation:', '{module_name:', 'ucommand,',
> 'module_complex_args:', '{},', 'module_args:', 'ubash -c "date
> +%Y-%m-%d"},', 'stdout_lines:', '[2016-04-22],', 'warnings:',
> '[]}.sql'])

Here you can see that {{ datestamp }} was replaced by:

{changed:', 'True,', 'end:', '2016-04-22 15:07:30.816204,', 'stdout:',
'2016-04-22,', 'cmd:', '[bash,', '-c,', 'date +%Y-%m-%d],', 'rc:',
'0,', 'start:', '2016-04-22 15:07:30.810278,', 'stderr:', ',',
'delta:', '0:00:00.005926,', 'invocation:', '{module_name:',
'ucommand,', 'module_complex_args:', '{},', 'module_args:', 'ubash -c
"date +%Y-%m-%d"}

which is NOT what you want :)

Best,
Felix
--
Felix Fontein -- fe...@fontein.de -- https://felix.fontein.de/

Joe Louthan

unread,
Apr 25, 2016, 9:40:22 AM4/25/16
to Ansible Project, fe...@fontein.de
That's it! Thank you!

To avoid being "that guy", here is the working playbook:

---
- hosts: dbserver
  remote_user: jlouthan
  tasks:
      - name: Get current timestamp
        local_action: command bash -c 'date +%Y-%m-%d.%H%M'
        # Consider switch this to a shell module with date command
        register: timestamp
        run_once: true

      - debug: var=timestamp.stdout

      - name: Get current datestamp
        local_action: command bash -c 'date +%Y-%m-%d'
        # Consider switch this to a shell module with date command
        register: datestamp
        run_once: true

      - debug: var=datestamp.stdout

      - name: Backup dbname Database
        mysql_db: "state=dump name=dbname target=~jlouthan/dbname.{{ timestamp.stdout }}.sql"
        become: yes
        become_method: sudo

      - name: See the DB Backups
        shell: ls -la ~jlouthan/ | grep {{ datestamp.stdout }}
        register: dumpdb

      - debug: var=dumpdb.stdout_lines

      - name: Make sure that the dbname DB Backups look good before you continue
        pause:

This playbook:
  1. Gets current date and time stamps from the remote machine (as oppose to the local machine that is running Ansible. Something to keep in mind if you have servers in different timezones) - Note: the debug lines for date and time stamps are merely there for me to see what stamp should I be seeing 
  2. Backup database using the timestamp within the resulting file name
  3. Double check using just the datestamp (as oppose to the fulltime stamp) and making sure that the backup looks good

Matt Martz

unread,
Apr 25, 2016, 9:54:13 AM4/25/16
to ansible...@googlegroups.com, fe...@fontein.de
Also, just as an FYI, this can be achieved without calling the date command:

---
- hosts: all
  tasks:
    - set_fact:
        datestamp: "{{ ansible_date_time.date }}"
        timestamp: "{{ '%s.%s%s'|format(ansible_date_time.date, ansible_date_time.hour, ansible_date_time.minute) }}"

    - debug:
        msg: "{{ item }}"
      with_items:
        - "{{ datestamp }}"
        - "{{ timestamp }}"



--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible-proje...@googlegroups.com.
To post to this group, send email to ansible...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ansible-project/b3befc8a-0ea3-4f17-bc63-dfc04f7d1ac8%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



--
Matt Martz
@sivel
sivel.net
Reply all
Reply to author
Forward
0 new messages