No man pages, but almost
The AWS Command Line Interface, which is available in Debian,
provides no man page. Instead, that tool has an integrated help system,
which allows you to run commands such as aws rds
help
, that, for what I have seen, generates some
reStructuredText, then converts it to a man page in troff format, then
calls troff to convert it to text with basic formatting, and eventually
passes it to a pager. Since this is close to what man does, the
result looks like a degraded man page, with some features missing such
as the adaptation to the terminal width.
Well, this is better than nothing, and better than what many
under-documented tools can offer, but for several reasons, it still
sucks: most importantly, it does not respect administrators' habits and
it does not integrate with the system man database. You it does not
allow you to use commands such as apropos
,
and you will get no man page name auto-completion from your shell since
there is no man page.
Generate the man pages
Now, since the integrated help system does generate a man page internally, we can hack it to output it, and save it to a file:
Description: Enable a mode to generate troff man pages The awscli help system internally uses man pages, but only to convert them to text and show them with the pager. This patch enables a mode that prints the troff code so the user can save the man page. . To use that mode, run the help commands with an environment variable OUTPUT set to 'troff', for instance: OUTPUT='troff' aws rds help Forwarded: no Author: Tanguy Ortolo <tanguy+debian@ortolo.eu> Last-Update: 2016-11-22 Index: /usr/lib/python3/dist-packages/awscli/help.py =================================================================== --- /usr/lib/python3/dist-packages/awscli/help.py 2016-11-21 12:14:22.236254730 +0100 +++ /usr/lib/python3/dist-packages/awscli/help.py 2016-11-21 12:14:22.236254730 +0100 @@ -49,6 +49,8 @@ Return the appropriate HelpRenderer implementation for the current platform. """ + if 'OUTPUT' in os.environ and os.environ['OUTPUT'] == 'troff': + return TroffHelpRenderer() if platform.system() == 'Windows': return WindowsHelpRenderer() else: @@ -97,6 +99,15 @@ return contents +class TroffHelpRenderer(object): + """ + Render help content as troff code. + """ + + def render(self, contents): + sys.stdout.buffer.write(publish_string(contents, writer=manpage.Writer())) + + class PosixHelpRenderer(PagingHelpRenderer): """ Render help content on a Posix-like system. This includes
This patch must be applied from the root directory with patch -p0
, otherwise GNU patch will not
accept to work on files with absolute names.
With that patch, you can run help commands with an environment
variable OUTPUT='troff'
to get
the man page to use it as you like, for instance:
% OUTPUT='troff' aws rds help > aws_rds.1 % man -lt aws_rds.1 | lp
Generate all the man pages
Now that we are able to generate the man page of any aws command, all we need to generate all of them is a list of all the available commands. This is not that easy, because the commands are somehow derived from functions provided by a Python library named botocore, which are derived from a bunch of configuration files, and some of them are added, removed or renamed. Anyway, I have been able to write a Python script that does that, but it includes a static list of these modifications:
#! /usr/bin/python3 import subprocess import awscli.clidriver def write_manpage(command): manpage = open('%s.1' % '_'.join(command), 'w') command.append('help') process = subprocess.Popen(command, env={'OUTPUT': 'troff'}, stdout=manpage) process.wait() manpage.close() driver = awscli.clidriver.CLIDriver() command_table = driver._get_command_table() renamed_commands = \ { 'config': 'configservice', 'codedeploy': 'deploy', 's3': 's3api' } added_commands = \ { 's3': ['cp', 'ls', 'mb', 'mv', 'presign', 'rb', 'rm', 'sync', 'website'] } removed_subcommands = \ { 'ses': ['delete-verified-email-address', 'list-verified-email-addresses', 'verify-email-address'], 'ec2': ['import-instance', 'import-volume'], 'emr': ['run-job-flow', 'describe-job-flows', 'add-job-flow-steps', 'terminate-job-flows', 'list-bootstrap-actions', 'list-instance-groups', 'set-termination-protection', 'set-visible-to-all-users'], 'rds': ['modify-option-group'] } added_subcommands = \ { 'rds': ['add-option-to-option-group', 'remove-option-from-option-group'] } # Build a dictionary of real commands, including renames, additions and # removals. real_commands = {} for command in command_table: subcommands = [] subcommand_table = command_table[command]._get_command_table() for subcommand in subcommand_table: # Skip removed subcommands if command in removed_subcommands \ and subcommand in removed_subcommands[command]: continue subcommands.append(subcommand) # Add added subcommands if command in added_subcommands: for subcommand in added_subcommands[command]: subcommands.append(subcommand) # Directly add non-renamed commands if command not in renamed_commands: real_commands[command] = subcommands # Add renamed commands else: real_commands[renamed_commands[command]] = subcommands # Add added commands for command in added_commands: real_commands[command] = added_commands[command] # For each real command and subcommand, generate a manpage write_manpage(['aws']) for command in real_commands: write_manpage(['aws', command]) for subcommand in real_commands[command]: write_manpage(['aws', command, subcommand]) 'sync', 'website']}
This script will generate more than 2,000 man page files in the current directory; you will then be able to move them to /usr/local/share/man/man1.
Since this is a lot of man pages, it may be appropriate to
concatenate them by major command, for instance all the aws rds
together…
3 comments
wednesday 23 november 2016 à 20:40 Colin Watson said : #1
wednesday 23 november 2016 à 21:08 Tanguy said : #2
tuesday 06 december 2022 à 11:38 Anthony Foiani said : #3