Add --disable-hook-validation
diff --git a/certbot/cli.py b/certbot/cli.py
index bcb7785c59e..f3decec0598 100644
--- a/certbot/cli.py
+++ b/certbot/cli.py
@@ -356,7 +356,8 @@ def parse_args(self):
                         " {0} conflicts with dialog_mode").format(arg)
                     )
 
-        hooks.validate_hooks(parsed_args)
+        if parsed_args.validate_hooks:
+            hooks.validate_hooks(parsed_args)
 
         return parsed_args
 
@@ -792,6 +793,14 @@ def prepare_and_parse_args(plugins, args, detect_defaults=False):
         "For this command, the shell variable $RENEWED_LINEAGE will point to the"
         "config live subdirectory containing the new certs and keys; the shell variable "
         "$RENEWED_DOMAINS will contain a space-delimited list of renewed cert domains")
+    helpful.add(
+        "renew", "--disable-hook-validation",
+        action='store_false', dest='validate_hooks', default=True,
+        help="Ordinarily the commands specified for --pre-hook/--post-hook/--renew-hook"
+        " will be checked for validity, to see if the programs being run are in the $PATH,"
+        " so that mistakes can be caught early, even when the hooks aren't being run just yet."
+        " The validation is rather simplistic and fails if you use more advanced"
+        " shell constructs, so you can use this switch to disable it.")
 
     helpful.add_deprecated_argument("--agree-dev-preview", 0)
 
diff --git a/certbot/tests/cli_test.py b/certbot/tests/cli_test.py
index 671da16f05f..adbde1d3e33 100644
--- a/certbot/tests/cli_test.py
+++ b/certbot/tests/cli_test.py
@@ -651,6 +651,18 @@ def test_quiet_renew(self):
         out = stdout.getvalue()
         self.assertEqual("", out)
 
+    def test_renew_hook_validation(self):
+        self._make_test_renewal_conf('sample-renewal.conf')
+        args = ["renew", "--dry-run", "--post-hook=no-such-command"]
+        self._test_renewal_common(True, [], args=args, should_renew=False,
+                                  error_expected=True)
+
+    def test_renew_no_hook_validation(self):
+        self._make_test_renewal_conf('sample-renewal.conf')
+        args = ["renew", "--dry-run", "--post-hook=no-such-command",
+                "--disable-hook-validation"]
+        self._test_renewal_common(True, [], args=args, should_renew=True,
+                                  error_expected=False)
 
     @mock.patch("certbot.cli.set_by_cli")
     def test_ancient_webroot_renewal_conf(self, mock_set_by_cli):

As discussed in #3020.
