flymake-shell works with any shell of your choice. Default it uses [[Bash]].

This doesn't actually seem to do anything for me. Can you give an example of some code that would cause an error to crop up? I tried some "fi" without if, but it does nothing.

It does work for me but the "-n" option doesn't find all errors.  For example, <i>exit ""</i> is syntactically correct but <i>exit</i> needs an argument which you will not be told.

    ;;; Flymake Shell mode
    
    (require 'flymake)
    
    (defcustom flymake-shell-of-choice
      "/bin/bash"
      "Path of shell.")
    
    (defcustom flymake-shell-arguments
      (list "-n")
      "Shell arguments to invoke syntax checking.")
    
    (defconst flymake-allowed-shell-file-name-masks
      '(("\\.sh$" flymake-shell-init))
      "Filename extensions that switch on flymake-shell mode syntax checks.")
    
    (defcustom flymake-shell-err-line-pattern-re
      '(("^\\(.+\\): line \\([0-9]+\\): \\(.+\\)$" 1 2 nil 3))
      "Regexp matching JavaScript error messages.")
    
    (defun flymake-shell-init ()
      (let* ((temp-file (flymake-init-create-temp-buffer-copy
                         'flymake-create-temp-inplace))
             (local-file (file-relative-name
                          temp-file
                          (file-name-directory buffer-file-name))))
        (list flymake-shell-of-choice (append flymake-shell-arguments (list local-file)))))
    
    (defun flymake-shell-load ()
      (setq flymake-allowed-file-name-masks (append flymake-allowed-file-name-masks flymake-allowed-shell-file-name-masks))
      (setq flymake-err-line-patterns (append flymake-err-line-patterns flymake-shell-err-line-pattern-re))
      (flymake-mode t)
      (local-set-key (kbd "C-c d") 'flymake-display-err-menu-for-current-line))
    
    (provide 'flymake-shell)
    
    ;;; flymake-shell.el ends here

You may want to invoke flymake-shell when sh-mode loads.

    (require 'flymake-shell)
    (add-hook 'sh-mode-hook 'flymake-shell-load)
