In general there can be many reasons why scripts behave differently under CGI than on the normal user shell:
- Permissions: CGI scripts are run under a user with low privilges. Operations that succeed for normal users can fail for the www-data user, or whatever it's called. This is probably the most commonly observed difference.
- Environment variables: CGI scripts usually have far less of the "usual" environment variables set
- Security context: on selinux enabled systems, CGI scripts are run in a different security context that forbids certain operations even if normal permissions would allow them (like opening a socket, writing to files in a home dir). This is probably the hardest difference to find if you're not aware that such a thing exists.
- Output interpretation: usually the output of a CGI script is interpreted by a browser, whereas the user often looks at the output of a shell script directly.