How do I get Postgres DO $$ to work from the bash prompt?
Using \ to escape the dollar $ 

echo \$PATH
$PATH


Reference to psql doc, in order to execute multi commands, they also provide 3 ways to work around as below

1) Repeats -c option 

psql -c 'SELECT now()' -c 'SELECT * FROM foo;'


2) Combines echo and psql 

echo 'SELECT now() ; SELECT * FROM foo;' | psql


3) Uses psql and EOF

psql &lt;&lt;EOF
\x     
SELECT now(); 
SELECT * FROM foo;
EOF


Besides, considering changing rolename text to rolename RECORD to avoid ERROR:  missing FROM-clause entry for table (record type)


  Record variables are similar to row-type variables, but they have no
  predefined structure. They take on the actual row structure of the row
  they are assigned during a SELECT or FOR command


In terms of your case, please careful with DROP ROLE due to dependencies (refer: dropping role)


  If DROP ROLE is attempted while dependent objects still remain, it
  will issue messages identifying which objects need to be reassigned or
  dropped.


Last but not least, here's my example

#### Using psql and EOF
psql &lt;&lt; EOF
DO \$$
DECLARE
  v_role record; 
BEGIN
  for v_role in select rolname from pg_roles where rolname not in ('postgres', 'pg_signal_backend', 'TAP')
  loop
    raise notice '%', v_role.rolname;
    execute 'DROP ROLE ' || v_role.rolname;  
  end loop;
END
\$$;
EOF

#### Using echo and psql
echo "
DO \$$
DECLARE
  v_role record; 
BEGIN
  for v_role in select rolname from pg_roles where rolname not in ('postgres', 'pg_signal_backend', 'TAP')
  loop
    raise notice '%', v_role.rolname;
    execute 'DROP ROLE ' || v_role.rolname;  
  end loop;
END
\$$;
" | psql